Parse-cache-memory - A cache library customized for parse-server queries

  • Part 1:

Hello, today I want to tell you about the parse-cache-memory package. This package is a tool that you can use to increase performance by caching the results of Parse Server queries in memory. With this package, you can run frequently repeated and unchanged queries faster and put less load on Parse Server. To learn how this package works and how to use it, keep reading.:blush:

  • Part 2:

To use the parse-cache-memory package, you first need to install it with npm. You can do this with the npm install parse-cache-memory command. Then you need to require this package along with Parse SDK.

const Parse = require('parse/node');
new (require('parse-cache-memory'))({
    max: 5000, // maximum number of items that can be stored for each class (className)
    maxSize: 50000, // total maximum number of items that can be stored across all classes
    ttl: 1000 * 60 * 5, // time-to-live for items in the cache, here set to 10 minutes
    allowStale: false, // determines whether items can be used after their ttl has expired
    updateAgeOnGet: false, // determines whether an item's age is updated when it's retrieved using "get"
    updateAgeOnHas: false, // determines whether an item's age is updated when it's checked using "has"
  • This way you can use this package with Parse SDK.:blush:

  • Part 3:

The parse-cache-memory package adds new methods to Parse queries. With these methods, the results of queries are automatically cached and retrieved from the cache when you run the same query again. These methods are: findCache, firstCache, countCache, distinctCache, aggregateCache, eachCache, eachBatchCache, mapCache, reduceCache, filterCache and subscribeCache. You can use these methods instead of normal Parse queries. For example:

const query = new Parse.Query('GameScore');
query.equalTo('playerName', 'Dan Stemkoski');
const data = await query.findCache();
This way you can get the result of the query from the cache.😊
  • Part 4:

The parse-cache-memory package also hooks the save, saveAll, destroy and destroyAll methods of Parse objects. With these methods, when you save or delete objects, the cache is cleared. This prevents old or corrupted data from remaining in the cache. You can use these methods instead of normal Parse objects. For example:

const gameScore = new Parse.Object('GameScore');
gameScore.set('score', 1337);
gameScore.set('playerName', 'Sean Plott');
gameScore.set('cheatMode', false);

This way you can clear the cache after saving the object.:blush:

Some test results:



Thank you!!! Just in time

1 Like

Is this for client side caching?

Also just a side note that if your queries are taking 4s to resolve, I would guess that there are more optimisations that could be made (such as indexing)

I use it server-side in my cloud code and it’s awesome. The execution time drops from 200ms to 1ms. One improvement that could be made is to allow tweaking the caching settings per function. For example:

const resultA = await queryA.firstCache({useMasterKey: true, ttl: 1000 * 60 * 5});
const resultB = await queryB.firstCache({useMasterKey: true, ttl: 2000 * 60 * 5});

As far as I know currently you can only set the caching parameters globally when you initiate the module.

1 Like

To increase the query difficulty, a lot of data was used in the tests with complex aggregate. Therefore the first query time is long.

Thank you for testing the package and expressing your satisfaction.

I will consider your feedback, as you said it is defined globally

1 Like

Does it respect ACLs/sessionToken when used server side? Sounds like an interesting package

Yes it respect ACLs/sessionToken when used server side. You should try. I am waiting more usage for parse server followers.

1 Like

Very interesting!

Thanks for releasing this.

1 Like

Thank you, good use.

This is great. Thank you for contributing! Would be nice to be able to pass a flag so that it will “fall back” to the DB if the cache returns zero records.

1 Like

If there is no data in the cache, the Db is already queryed and cached again. :raised_hands:

1 Like

thanks for sharing your tool @rgunindi - I have many clients making requests so it’s hard to introduce it there. Is there a way to instrument parse-server running in Docker, to use this module?

1 Like

You can install it into your parse-server in docker.

Is it enough to require it on the backend to make it work? Or would I need to customize anything?

It is sufficient to use the specified functions to apply the cache. You can use it with default settings.

Ok I was hoping for a drop in plugin, but how you’re suggesting to use those functions which doesn’t make sense for my use case. I run a vanilla parse server using docker and clients call it. How and where would I call the cache functions in the server?

I have some questions for your setup, In your Parse Server, which directory are your cloud functions defined in?
When starting the Parse Server on Docker, do you specify the disk address for the cloud functions?
Can you share the full path to the file where you have defined your cloud functions?

Sure, I am using docker image: parseplatform/parse-server:5.4.0-beta.1

then I am copying my cloud functions:

COPY ./provisioning/cloud-functions /parse-server/cloud/

Then installing dependencies:

RUN cd /parse-server && npm i @parse/[email protected] [email protected] [email protected]

Hope it helps, I’d love to use your module!

I think you can do it this way.
Before you should change the cloud function
example: …query.find() - > to …query.findCache() and do it other functions like this.
Dont, forget! adding this line.
into cloud function file or main.js file

new (require('parse-cache-memory'))({ ttl: 30 * 60 * 1000 })  // ex 30min

→ add cache package.
RUN cd /parse-server && npm i @parse/[email protected] [email protected] [email protected] parse-cache-memory