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

Database layer for Idempotency Keys persistence. #1

Open
marcoonroad opened this issue Jun 3, 2018 · 3 comments
Open

Database layer for Idempotency Keys persistence. #1

marcoonroad opened this issue Jun 3, 2018 · 3 comments

Comments

@marcoonroad
Copy link

marcoonroad commented Jun 3, 2018

Let's imagine a clusterized network (either physical or virtual/dockerized). Let's also suppose that our clients are ERP API integrations (no browser here). How can we ensure that duplicated requests don't spend money more than once? The solution is to persist such Idempotency Key + Request/Response information on some shared store for the running micro-service instances.

Good candidates for the backend storage are:

  • 🐘 Postgres, due the widespread usage.
  • 🔴 Redis, due the TTL of keys support.

I'm just opening this issue to start a nice discussion here, and, if you would approve, I could as well open a Pull-Request to implement that. 😄

Thanks in advance! 👍

@marcoonroad marcoonroad changed the title Database layer for Idempotence Keys persistence. Database layer for Idempotency Keys persistence. Jun 11, 2018
@chris-jamieson
Copy link
Contributor

Hey @marcoonroad apologies I didn't see this post earlier.

Absolutely agree that using some persistent store for idempotency keys would make sense.

There are several good cache managers for Node which incorporate support for different stores (a favourite of mine is Node Cache Manager.

Perhaps a good approach to this would be to allow different stores to be supported (e.g. in-memory by default, redis / postgres / mongo etc. if specified by config).

Would be happy to discuss further and PRs warmly welcomed.

@marcoonroad
Copy link
Author

No problem, @jamiesoncj, it's quite hard to be up-to-date with GitHub notifications nowadays, they have a poor support for thread notifications anyways.

Redis is indeed one of the best for caching, 'cause it can asynchronously perform an on-disk backup (quite good when the server/machine crashes, different of Memcached, used to optimize data retrieval) and supports Time-to-Live on keys.

What about the initial implementation offer in-memory and Redis backends?
Thanks for the reply. o/

@chris-jamieson
Copy link
Contributor

chris-jamieson commented Aug 29, 2018

Great, if you want to produce a PR for Redis option that would be great.

Initially this can be quite simple - the main function should accept an options argument, which can contain cache-related keys, and also might allow us to set some other options e.g. specify the request header for the module to check (example below).

Can I suggest that the signature might be something like this:

var idempotency = require('@optimuspay/express-idempotency');

// Example for in-memory cache
var options = {
  requestHeader: 'Idem-Key', // default: 'Idempotency-Key' - this is not yet implemented
  cache: {
    store: 'memory',
    options: { // lruOptions if store is memory (see https://github.com/isaacs/node-lru-cache)
      max: 500,
      length: function (n, key) { return n * 2 + key.length },
      maxAge: 10000,
    }
  }
};

// Example for Redis cache
var options = {
  requestHeader: 'Idem-Key', // default: 'Idempotency-Key' - this is not yet implemented
  cache: {
    store: 'redis',
    options: { // options for redis.createClient if store is Redis (see https://github.com/NodeRedis/node_redis#options-object-properties)
      host: '127.0.0.1',
      port: 6379,
      path: null,
    },
    // redisClient: client, // instead of options property above, an initialised Redis client from `redis.createClient();` could be passed in here
  }
};

app.use(idempotency(options));

Look forward to your suggestions - the above is just an initial idea.

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

No branches or pull requests

2 participants