{"id":21944254,"url":"https://github.com/michaelkrone/monrule","last_synced_at":"2026-05-06T12:33:20.115Z","repository":{"id":57302589,"uuid":"53543504","full_name":"michaelkrone/monrule","owner":"michaelkrone","description":"A simple cache to persist expensive function results","archived":false,"fork":false,"pushed_at":"2017-07-07T14:54:58.000Z","size":46,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-28T19:03:50.594Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/michaelkrone.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-03-10T00:58:54.000Z","updated_at":"2016-11-04T11:03:21.000Z","dependencies_parsed_at":"2022-09-20T17:11:52.374Z","dependency_job_id":null,"html_url":"https://github.com/michaelkrone/monrule","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michaelkrone%2Fmonrule","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michaelkrone%2Fmonrule/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michaelkrone%2Fmonrule/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michaelkrone%2Fmonrule/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/michaelkrone","download_url":"https://codeload.github.com/michaelkrone/monrule/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244982057,"owners_count":20542300,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-29T04:15:11.846Z","updated_at":"2026-05-06T12:33:15.089Z","avatar_url":"https://github.com/michaelkrone.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# monrule\nA simple cache to persist expensive idempotent function results in a mongodb database with mongoose.\n\n```js\nconst fibonacci = require('fibonacci');\nconst FunctionCache = require('monrule').FunctionCache;\n\nconst cache = new FunctionCache(fibonacci.iterate, {mongoose});\n\n// get a simple wrapper function, you might also call cache.get(...)\nlet getFibonacci = cache.getWrapper();\n\n// fills the cache\ngetFibonacci(10000).then(result =\u003e ...); // 1 - 10 seconds\n// reads from the cache\ngetFibonacci(10000).then(result =\u003e ...);; // 1 - 10 milliseconds\n\t\n// promise, invalidate cache results based on a query\nc.invalidate({data.number: 13});\n// promise, clear all cached results\nc.clear(); \n```\n\n## How it works\nWhen creating a new `FunctionCache`, the source of the passed function is hashed. If the wrapped function is called,\na second hash is created from the arguments of the function. These two hashes plus an optional namespace represent the\ncache key and identify the stored result. Therefore the function has to be idempotent/referential transparent.\n\n## FunctionCache API\n\ndebuglog: `monrule:cache`\n\n### `new FunctionCache(Function function, [Object options])`\nCalls the wrapped function and looks up a cached result for the given arguments. If no cache result can be found the\nwrapped function is called and the result is cached in the database and returned.\n\n`function`: A Function which result should be cached. Note that this has to be an idempotent and referential transparent function. If the source of\nthe function changes, a new hash will be generated the next time the cache is created.\n\n`options`: \n\n`mongoose`: `Object` A mongoose instance used to communicate with the database\n\n`[modelName]`: `String` Name of the model to store the results with, defaults to 'ObjectBucket'. If the model is a registered mongoose\nmodel it will be used.\n\n`[namespace]`: `String` A prefix for the id, will be used to invalidate all objects with this prefix, defaults to 'FunctionCache'\n\n`[saveWrite]`: `Boolean`, defaults to true. If set to false, the function result will be returned without waiting for the database write operation to finish.\n\n`[resolver]`: `Function` A function that is called for every id generation with the arguments of the cached function. It might return any truthy value.\nThis is usefull if only a fraction of the arguments should be considered for generating an object id. This is usefull if not the complete arguments\nneed to be hashed, e.g. if objects can be identified by its id:\n\n```js\nconst cache = new FunctionCache(fn, {resolver: (d1, d2) =\u003e [d1._id, d2._id]});\n\nfunction compute(document1, document2) {\n\t// generate some data\n}\n\n```\n\n### `Promise get(Arguments arguments)`\nCalls the wrapped function and looks up a cached result for the given arguments. If no cache result can be found the\nwrapped function is called and the result is cached in the database and returned.\n```js\nf.get(a, b, c);\n```\n\n### `Function getWrapper()`\nReturns the wrapped function to work with the cache like a normal function. Calls the `get` method with the correct\nclass bound to `this`.\n```js\nconst f = fCache.getWrapper();\nf(a, b, c);\n```\n\n### `Promise clear()`\nClears the cache and removes all entries with the namespace set in the options. If no namespace has been\nset, the default namespace will be used. The promise resolves to the mongodb response for the remove command.\n```js\nfCache.clear().then(...);\n```\n\n### `Promise invalidate(Object queryObject)`\nInvalidate (read: remove) all results that match the query object. Note that the cached data is per default saved as\na `data` object, so you might prefix your queries accordingly. The promise resolves to the mongodb response for the remove command.\n```js\nfCache.invalidate({'data.prop': dataValue}).then(...);\n```\n\n### static `String getId(a, b, c, ...)`\nGenerate a hash for the given arguments, if a resolver function is given in the options the resolver is called\nwith the given arguments and the result of the resolver function is used to generate a hash.\n```js\nFunctionCache.getId(a, b, c);\n```\n\n## ObjectStore API\n\ndebuglog: `monrule:store`\n\n### Options\n\n`mongoose`: A mongoose instance used to communicate with the database\n\n`[modelName]`: Name of the model to store the results with, defaults to 'ObjectBucket'\nIf no such model has been registered, a standard model will be used.\n\n```js\nconst ObjectStore = require('monrule').ObjectStore;\nconst oStore = new ObjectStore({mongoose: require('mongoose')});\n```\n\n### `Promise set(String id, Promise|Function|Object value)`\nSet a value in the store with the given id. If a value with this id exists it will be overwritten.\nReturns a Promise resolving to the given value or the result of the value function or the resolved value\nof the value Promise.\n```js\noStore.set(1, {awe: 'some'}).then(...);\n```\n\n### `Promise get(Promise|Function|String id)`\nGet an object from the store by the given id or null if it does not exist. If `id` is a Function or Promise it\nwill be called/resolved.\n```\noStore.get(1).then(r =\u003e r === {awe: 'some'}); // true\n```\n\n### `Promise delete(Promise|Function|String id)`\nRemove the object with the given id. If `id` is a Function or Promise it\nwill be called/resolved.\n```js\nfCache.delete(1).then(...);\n```\n\n### `Promise has(String id)`\nMap interface method, check if an entry with the given id exists.\n```js\nfCache.has(id).then(b =\u003e b === true || b === false);\n```\n\n### Todo\n* make object-store a plugin\n* add redis adapter/plugin\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmichaelkrone%2Fmonrule","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmichaelkrone%2Fmonrule","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmichaelkrone%2Fmonrule/lists"}