Coder Social home page Coder Social logo

emcache's Introduction

emcache

A minimal in-memory cache backed by a datastore of your choice.

Rationale

  • Why another in-memory cache now?

    Fair question that. After all, there's nothing new under the sun. The primary push, is to have the developer in me not die, amidst all the JIRAs that move me away from comfort zones.

  • So, is that all? No valid reasons?

    Won't quite jump that direction, yet. I had a specific use case of our applications using node-cache but not handling some parts that come home often.

  • Are there no alternatives?

    To be honest, there is nothing new under the sun, again. But, what's a developer who doesn't want their own implementation? Jokes aside, while node-cache provides a good set of APIs to access the in-memory cache, it is not backed. Not to mention, some concerns we have specific to our stack.

  • Well, what are they?

    Considering some cases where our processes reboot, this becomes an awkward space to be in. A good choice then, would be to have the existing in-memory cache work with process.on and SIGINT/SIGTERM, but no side-cars here, apparently.

    Add to it, the flexibility such a cache would provide in becoming a terminator, shouting I'm back .

  • So, does it cover the rest of the APIs that node-cache or alternatives provide?

    No, not yet. It is as basic as it gets, at the moment. A setter with a fluent API that doubles as a delete, a getter, and an entire cache retrieval is what it supports at the top level API. flush, stats, and QoL APIs, are things I'd like over time.

API

  • get(key)
  • set(key, value, expiryInMS)
  • values
  • stats

Examples

Initialisation

const cacheName = 'emcache'
let cache = new EmCache({
  name: cacheName,
  inSink: null,
  outSink: null,
  syncOnSet: false
})

Set a key with an expiry.

cache.set('AMZ-1001', { name: 'Amazon', description: `Amazon test` }, 1000)

Set a key and chain another set operation.

cache
  .set('AMZ-1001', { name: 'Amazon', description: `Amazon test` }, 1000)
  .set('FK-1002', { name: 'Flipkart', description: 'Flipkart shopping' })

Delete a key. Setting a null/undefined deletes the key.

const timer = setTimeout(() => {
  cache.set('AMZ-1001', null)  // DELETE operator
  clearTimeout(timer)
}, 3000)

Get the stats of a particular cache.

console.log(JSON.stringify(cache.stats, null, 1))
{
 "keys": {
  "count": 1,
  "keys": [
   "TE-003"
  ]
 },
 "expiries": {}
}

Parameters

syncOnSet

The syncOnSet boolean parameter provides a way to continuously sync/flush the cache to a store.

Note: Use this parameter with caution since it introduces write time overheads.

inSink

The inSink parameter to the constructor provides a datasource to initialise the cache. This is a function that returns a data object that initialises the cache, like a redis hash.

If not provided, EmCache uses a caches file at the local path as a JSON serialised source.

  const { createClient } = require('redis');
  const client = createClient()
  client.connect()
  async function inSink() {
    const data = await client.HGETALL(cacheName)
    // const data = JSON.parse(await client.GET(cacheName || '{}'))
    return data || {}
  }
  let cache = new EmCache({
    name: cacheName,
    inSink,
    outSink: null
  })

outSink

The outSink parameter to the constructor provides a datasource to flush the cache into, when the process exits, terminates, or is terminated. This is a function that pushes data to your backing store.

If not provided, EmCache uses a caches file at the local path as a JSON serialised source.

  const { createClient } = require('redis');
  const client = createClient()
  client.connect()
  async function inSink() {
    const data = await client.HGETALL(cacheName)
    // const data = JSON.parse(await client.GET(cacheName || '{}'))
    return data || {}
  }
  async function outSink(data) {
    await client.HMSET(cacheName, Object.entries(data))
    // await client.SET(cacheName, JSON.stringify(data))
  }
  let cache = new EmCache({
    name: cacheName,
    inSink,
    outSink
  })

emcache's People

Contributors

techiev2 avatar

Watchers

 avatar

emcache's Issues

Process does not terminate on Ctrl-C.

Steps to replicate.

  • Create a cache.
  • Start a HTTP server listening on some port.
  • Use the cache/not within the module.
  • Attempt to stop the process with a SIGINT

The server process does not get killed and keeps running in the background. This is unlike a regular HTTP Server (node:http/express) and breaks deployments given the bound ports.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.