Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change (some) callbacks to only trigger when complete. #23

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Change (some) callbacks to only trigger when complete. #23

wants to merge 1 commit into from

Conversation

JaredReisinger
Copy link

This is a proof-of-concept PR for the issue raised in #22. In particular, the caller-provided callback is only called when all of the cache modules have completed.

In making this change, I discovered several other issues that should probably be addressed.

  • In general the cache-service "writing" APIs (.set(), .mset(), .del(), and .flush()) don't define what the caller-provided callback will be passed on success, failure, or partial failure. (I suspect cache-service will need to define something like an "aggregate error" to encapsulate the "one or more modules had a problem" scenario.)

  • The .get() API implies (by "response... null on cache miss") that a cache miss should not pass an error value to the callback; this should likely be explicit. On the other hand, cache-service's implementation handles module .get() errors by simply trying the next module, so perhaps cache-misses should be handled by an error value, allowing any value (including null and undefined) for a cache-hit.

  • The module API doesn't specify what should be passed to the callback on success or failure. Is only the err argument used? Is nothing inspected, and the callback used only to indicate completion?

This is a proof-of-concept PR for the issue raised in
#22.  In particular, the
caller-provided callback is only called when _all_ of the cache modules
have completed.

In making this change, I discovered several other issues that should
probably be addressed.

* In general the cache-service "writing" APIs (`.set()`, `.mset()`,
  `.del()`, and `.flush()`) don't define what the caller-provided
  callback will be passed on success, failure, or partial failure.  (I
  suspect cache-service will need to define something like an "aggregate
  error" to encapsulate the "one or more modules had a problem"
  scenario.)

* The `.get()` API implies (by "response... null on cache miss") that a
  cache miss should _not_ pass an error value to the callback; this
  should likely be explicit.  On the other hand, cache-service's
  implementation handles module `.get()` errors by simply trying the
  next module, so perhaps cache-misses _should_ be handled by an error
  value, allowing _any_ value (including null and undefined) for a
  cache-hit.

* The _module_ API doesn't specify what should be passed to the callback
  on success or failure.  Is only the `err` argument used?  Is _nothing_
  inspected, and the callback used only to indicate completion?
@JaredReisinger
Copy link
Author

JaredReisinger commented Feb 1, 2017

Full disclosure: I'm writing a cache-service-file-system module for cache-service to have file-system-backed persistence for superagent, and also to use for a really cheap persistent data store... no dependencies on redis or memcached required, data is easily human readable and easily programmatically consumable by other tools. Also, my calling code is promise-based, so I expect for my .then() chains after a .set() to only happen after the data has been written to disk. (If I didn't have that requirement, I wouldn't put the following code in the .then(), I'd just continue immediately after calling .set().)

if (++moduleCallbacks === self.cachesLength){
// note: no errors are passed back!
cb(null);
}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about this some more, it should probably just use async's map() to make the .set() calls on all of the modules and collect the results. This is exactly the kind of synchronization management for which async was designed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant