GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Persisting node-cache · Issue #293 · node-cache/node-cache

Persisting node-cache #293

New issue
Copy link
New issue
Copy link
Open
Open
Persisting node-cache#293
Copy link

Description

@horak
horak
opened on Aug 13, 2022
Issue body actions

I am using node-cache for a dead simple string key/val lookup & I'd like the cache to persist across server restarts.

Would it be possible, to save the cache to, for example, a JSON file which I read into node-cache on server initialization?

Is this something folks already use node-cache for, or shall I look elsewhere?

Activity

  1. Themis3000 commented on Oct 6, 2022

    @Themis3000
    Themis3000
    on Oct 6, 2022
    More actions

    Seems technically possible. You could read all values with myNodeCache.data, store it in a json, then on server startup read that json file and readd the values with something like this (untested psudo-code. may or may not work, just used as example.):

    const success = myNodeCache.mset(Object.entries(loadedJsonObject).forEach(([key, value]) => {
      {key: key, val: value.v, ttl: value.t}
    }));

    This is most likely something others aren't doing with this library though. node-cache as far as I understand is meant only for caching temporary values. If you'd like long term data storage, I'd recommend something like jsoning as a replacement. It doesn't have the feature of ttl with automatic deletion, but it is persistent. Otherwise, if you're more adventurous, something like mongodb would be more robust for persistent data storage.

    If you do still want a extremely performant database with the ability to set ttl values that won't clear out every time you restart your program, you could use redis but it will be more complicated as it's a database ran separated from your script (like monngodb). It stores all data in memory, so it's very fast but the database it's self will clear out between restarts. You do not however need to restart the database every time you restart your program. It would be a solution that would make sense if the data you're storing doesn't need to be persisted, it would just be nice to have if it where between restarts.

    Otherwise, if some data needs to be persisted and other data does not need to be persisted, it is common practice to use a caching db like node-cache or redis in combination with a db built for persistence like jsoning or mongodb. That way all your temporary data can be stored in your caching database, and all the data that needs to persist can be stored in your persistent database. Don't feel like it's wrong to use 2 databases for 2 different purposes in that case.

    Let me know if you have any questions about that. I'll help you persist data between restarts of node-cache if you'd like, just know that's probably starting to reach outside of the intended use of the package. It will work though, so if that solution makes the most sense to you then go for it. Thought I'd just lay out other common solutions for you if you'd like to go for a more common/intended route

  2. horak commented on Oct 7, 2022

    @horak
    horak
    on Oct 7, 2022
    Author
    More actions

    I am currently using persistent-cache. It suits my needs well and seems similar to your recommendation, jsoning. +1 for keeping it simple.

    Thank you wholeheartedly for the detailed response; especially for the additional offer to help me find a solution!

    Reacted by Themis Megas, Andrew Moore and Matiss
  3. Themis3000 commented on Oct 7, 2022

    @Themis3000
    Themis3000
    on Oct 7, 2022
    More actions

    Awesome! Glad you found a good solution that fits your needs perfectly, good luck on your projects!

    Reacted by ... and Andrew Moore
  4. matys1 commented on Jan 25, 2023

    @matys1
    matys1
    on Jan 25, 2023
    More actions

    I use persistent-cache to cache the data when in local development since after every file save nodemon restarts the server and I use node-cache in prod when deployed.

  5. ve3 commented on Jan 31, 2023

    @ve3
    ve3
    on Jan 31, 2023
    More actions

    Currently there are warnings after installed persistent-cache

    4 moderate severity vulnerabilities

    Use with care.

  6. ve3 commented on Jan 31, 2023

    @ve3
    ve3
    on Jan 31, 2023
    More actions

    This is my implement persistent cache based on node-cache.

    /**
     * Make cache stay alive even the process started and ended and start again.
     * 
     * @link https://github.com/node-cache/node-cache/issues/293 The ideas.
     */
    
    
    'use strict';
    
    
    // import node & installed packages.
    import fs from 'node:fs';
    import NodeCache from 'node-cache';
    import path from 'node:path';
    
    
    export default class Cache {
    
    
        /**
         * @property {NodeCache} cacheObj The cache object using Node package.
         */
        #cacheObj = {};
    
    
        /**
         * @property {object} options The options.
         */
        #options = {};
    
    
        /**
         * 
         * @param {object} options Accept arguments.
         * @param {string} options.cacheJsonPath The cache JSON file full path. This file will be use for persistent cache across process end/start.
         * @param {object} options.cacheOptions The cache options. Currently use node-cache, see https://www.npmjs.com/package/node-cache.
         */
        constructor({} = {}) {
            const defaults = {
                cacheJsonPath: path.resolve(YOUR_APP_ROOT_PATH + '/.cache/cache.json'),
                cacheOptions: {},
            }
    
            this.#options = {
                ...defaults,
                ...arguments[0]
            }
    
            this.#prepareCacheFolder();
    
            this.#cacheObj = new NodeCache(this.#options.cacheOptions);
            this.#restoreCacheFile();
            this.#listenEvents();
        }// constructor
    
    
        /**
         * Listen cache class events to work.
         * 
         * @private This method was called from `constructor()`.
         */
        #listenEvents() {
            this.#cacheObj.on('set', (key, value) => {
                this.#writeAllCacheData(this.#cacheObj.data);
            });
    
            this.#cacheObj.on('del', (key, value) => {
                this.#writeAllCacheData(this.#cacheObj.data);
            });
    
            this.#cacheObj.on('expired', (key, value) => {
                this.#writeAllCacheData(this.#cacheObj.data);
            });
    
            this.#cacheObj.on('flush', () => {
                this.#writeAllCacheData(this.#cacheObj.data);
            });
        }// listenEvents
    
    
        /**
         * Prepare cache JSON file.
         * 
         * @private This method was called from `#prepareCacheFolder()`.
         */
        #prepareCacheFile() {
            const content = {};
    
            this.#writeAllCacheData(content);
        }// prepareCacheFile
    
    
        /**
         * Prepare cache folder where JSON cache file will be store.
         * 
         * @private This method was called from `constructor()`.
         * @returns {void}
         */
        #prepareCacheFolder() {
            if (fs.existsSync(this.#options.cacheJsonPath)) {
                // if file is already exists.
                // do nothing.
                return ;
            }
    
            const cacheDir = path.dirname(this.#options.cacheJsonPath);
            if (!fs.existsSync(cacheDir)) {
                fs.mkdirSync(cacheDir, {recursive: true});
                this.#prepareCacheFile();
            }
    
            // check again.
            if (!fs.existsSync(cacheDir)) {
                // if still not exists.
                throw new Error('The cache folder is not exists and could not be created. (' + cacheDir + ')');
            }
        }// prepareCacheFolder
    
    
        /**
         * Restore cache file.
         * 
         * @private This method was called from `constructor()`.
         */
        #restoreCacheFile() {
            const JSONContent = fs.readFileSync(
                this.#options.cacheJsonPath,
                {
                    'encoding': 'utf8',
                    'flag': 'r',
                }
            );
    
            this.#cacheObj.data = JSON.parse(JSONContent);
        }// restoreCacheFile
    
    
        /**
         * Write all cache data to JSON file.
         * 
         * @private This method was called from `#listenEvents()`, `#prepareCacheFile()`.
         * @param {mixed} data The data to write.
         */
        #writeAllCacheData(data) {
            const dataJSON = JSON.stringify(data, undefined, 4);
    
            fs.writeFileSync(
                this.#options.cacheJsonPath, 
                dataJSON,
                {
                    'encoding': 'utf8',
                }
            );
        }// writeAllCacheData
    
    
        /**
         * Returns the cache object on `#cacheObj` property.
         * 
         * @returns {object} Returns the cache object on `#cacheObj` property.
         */
        cacheObj() {
            return this.#cacheObj;
        }// cacheObj
    
    
    }
    

    Usage:

    import Cache from '../Libraries/Cache.mjs';
    
    const cacheObj = new Cache();
    const nodeCacheObj = cacheObj.cacheObj();
    const windowProcessID = process.ppid;
    const cacheKey = 'cache-' + windowProcessID;
    const cachedVal = nodeCacheObj.get(cacheKey);
    
    console.log('cached value: ', cachedVal);
    
    if (typeof(cachedVal) === 'undefined') {
        // if no cache.
        nodeCacheObj.set(cacheKey, 'hello world');
        console.log('cache was set.');
    }
    
    console.log('Retrieve cache again: ', nodeCacheObj.get(cacheKey));
    

    I hope it is useful for you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402503 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.