{"_id":"@analogculture/weave","_rev":"5-bcf9fd170a51604eb5742581ff9eb1f2","name":"@analogculture/weave","dist-tags":{"latest":"2.0.0"},"versions":{"0.0.1":{"name":"@analogculture/weave","version":"0.0.1","license":"MIT","bin":{"weave":"./bin/weave"},"main":"src/index.js","scripts":{"commit":"npx git-cz","test":"tap test --coverage-report","example":"cd example; npm i; npm start"},"dependencies":{"amqplib":"^0.5.2","chalk":"^2.4.1","cuid":"^2.1.1","dotenv":"^6.0.0","mongodb":"^3.0.10","node-fetch":"^2.1.2"},"devDependencies":{"tap":"^12.0.1","tape":"^4.9.1","cz-conventional-changelog":"^2.1.0","semantic-release":"^15.6.0"},"config":{"commitizen":{"path":"./node_modules/cz-conventional-changelog"}},"gitHead":"8fc9a7ec2f7df0a1dcca267ac44ac65f4ee34248","description":"Weave is a system of event driven generic resources and just one possible solution to a list of problems including fault tolerance, load distribution, predictability and scalability for servers that handle data and connect to a database.","_id":"@analogculture/weave@0.0.1","_npmVersion":"6.1.0","_nodeVersion":"10.1.0","_npmUser":{"name":"louisr","email":"louisrudner@gmail.com"},"dist":{"integrity":"sha512-/JfrO2aSEz2CjwlgjWfOzHP9OC/8tmUSVipyN+OhZPRfQnR2SGjT8MiXYxLu5DJBpFRaXdryC2LxB+x+01OanA==","shasum":"98065fa4fa664efbafcef251319ebc21b50c16a3","tarball":"https://registry.npmjs.org/@analogculture/weave/-/weave-0.0.1.tgz","fileCount":19,"unpackedSize":16006,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbK3EXCRA9TVsSAnZWagAAGcQP/3U1CCSYsrj8xSJr/orL\nUk6p0fKimOaE06wTbtqD9WkJ6WdZJL4m51o2BKsBCE3uqoIRkLYXhPkppizW\ntdWuNBtGt5qMQe+QQVdRsuuTl/jVWq7im1fbcECjjjc8xE3xjJgfEnCYdZXw\nc3tXnwIxO4ZmaLSulXMjO0HHiOTg9fmeeWeMKJd7sTnB+6a/FCbavNuNwlld\nDqgh9USfDS7SoEudjmRVp9v2RJ7M0cLVyJXbJf4QoOKPcqiBgWqPqxZ3FCOX\nI6IQSWFQ/AkK2wD15OhpUpVFVwbA2W/B/ozfAy/FV7nQdqjh3pru3HjyOnIY\nrvfQk06SAwoPrSlYBZbbeKbVI+gWvi4Zk5nKuPBJqpjoGzHyu/Qs4+nlPUEf\nVSfrjQJuyZ9x2oiJrrXU9MYl8Ve1Crw53rMdB1RHCZdbqiYD4npqTg2LEtfi\no/z9v4rYD5YVPDc2ttKspeDWWUw8+PxH6l3br4hKDHjy7qKCpm/4JTykKIos\nsSe8b4MBLLAwRUbVuZB/kmsTkHp6agMZoWcUaHg/GEAnrxBBf2xtZGLL/Ler\nnMbUklWAcD4PVFU7KU5VqhEL/cBO8DOHQXoLvWvKJYVCkJL+cxcTfNQHjjHb\nnOsRhgJDJhEwELKmjELXyWYsS5/+firFgImx/DoygIod0H3CixGZhuhS12VB\nq+IX\r\n=Zzpk\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQChgfKJpekEvp+ks2vQhQQZVGNYP1XGaCM9UGOBEFS7tgIgAKmb7UNzwsA25+6FkHjmut+e/KvmlzUCKGLmT2cz4PI="}]},"maintainers":[{"name":"louisr","email":"louisrudner@gmail.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/weave_0.0.1_1529573654473_0.2828893210731547"},"_hasShrinkwrap":false},"1.0.0":{"name":"@analogculture/weave","version":"1.0.0","license":"MIT","bin":{"weave":"./bin/weave"},"main":"src/index.js","scripts":{"cz":"npx git-cz","precommit":"lint-staged","test":"tap test --coverage-report","example":"cd example; npm i; npm start"},"lint-staged":{"*.js":["standard --fix","prettier --no-semi --single-quote --write","git add"]},"dependencies":{"amqplib":"^0.5.2","chalk":"^2.4.1","cuid":"^2.1.1","dotenv":"^6.0.0","mongodb":"^3.0.10","standard":"^11.0.1"},"devDependencies":{"cz-conventional-changelog":"^2.1.0","husky":"^0.14.3","lint-staged":"^7.2.0","semantic-release":"^15.6.0","tap":"^12.0.1","tape":"^4.9.1"},"config":{"commitizen":{"path":"./node_modules/cz-conventional-changelog"}},"gitHead":"fd77ed84a6c84728ab2718f5396cfc1eb8b8ca20","description":"Weave is a system of event driven generic resources and just one possible solution to a list of problems including fault tolerance, load distribution, predictability and scalability for servers that handle data and connect to a database.","_id":"@analogculture/weave@1.0.0","_npmVersion":"5.6.0","_nodeVersion":"10.0.0","_npmUser":{"name":"louisr","email":"louisrudner@gmail.com"},"dist":{"integrity":"sha512-dpDa+bW6RctKTTDPk6NSmysatAeE/xTWjZAtHO5uOr00Y56lhRtOM4BR19PBd5iK/b2mjzh0j/70XcVsd3bwHA==","shasum":"bac49e1c9a1cae7c12d6ee68e8450ece2f50e22d","tarball":"https://registry.npmjs.org/@analogculture/weave/-/weave-1.0.0.tgz","fileCount":18,"unpackedSize":15863,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbRFCYCRA9TVsSAnZWagAA9vsP/jWEC9X+YgI+yKfHrN6V\n4yjVVfXlmWeEJSJ/tjVqsDRHobBl5EUrhW067KqHCFlNcin7jXpWTRkM+A/t\nOnIbz8GLEOMVo7DVpI6icVhL9TnwdvjwoiTKCJykZQz7ZqdzzmpCaffWAVkc\nOn7WkauO9ozJ9DLTl4OGEYdCKZME9e44EoYj7kG4MSMpkS1ruY6H4bspLLfn\nWdYhCSobZ/1/ZPNQ2+IbgT3hp9ZN6+uFxxDBOR6Rvd5ApinrYBLzo/7Q/kSp\n90eioRgrOZ4vR1etbbfATr7hym9OPFGXFfPjC2U6Doye7iyvDAuamXfxdJbY\nW7UssCGf5wfBA0EiqjsaxRDnppeDlohMiUEloKVbzPD/bG3AileJIUMZI1E+\nCagCuN6+gI3Znp7ZW1Qm2La617JJKDeuzc9HiGm/kvCxhvw8mzaKmtS2JNRC\nd03Dy1z5cs1nfWPmevhQ9Yg2DoLx9ejY3UhDepk+B0bjMUDIZSBiIGcuohem\n0IlcUm2m5PvZrSSJ/u/xFmCG96CGeTeVZWWDsRk0A6VQcqnJrgvyvDeg0jn5\nXzmOwplw9nMpI+zLXbxp7dAaIL458mjk44oO5oPloiWB707rdAxMN8N0x3/8\na3ued/yv+RCao0CXVeIluH5HcOYZHpfNcFGmk9tpwRvAevlKIzQvDsC/vjOL\nCc5t\r\n=AY2j\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCgZ0v1yp4Ci++ORy/zWqXX2t9kpPeaS8YHGbBpZIGJ/wIhAIqMauae++TCOrld8p69EROqvoURm4yLmPNefgkMhNxt"}]},"maintainers":[{"email":"louisrudner@gmail.com","name":"louisr"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/weave_1.0.0_1531203736661_0.9085726767992073"},"_hasShrinkwrap":false},"2.0.0":{"name":"@analogculture/weave","version":"2.0.0","license":"MIT","bin":{"weave":"./bin/weave"},"main":"src/index.js","scripts":{"cz":"npx git-cz","precommit":"lint-staged","test":"tap test --coverage-report"},"lint-staged":{"*.js":["standard --fix","prettier --no-semi --single-quote --write","git add"]},"dependencies":{"amqplib":"^0.5.2","chalk":"^2.4.1","cuid":"^2.1.1","dotenv":"^6.0.0","mongodb":"^3.0.10","standard":"^11.0.1"},"devDependencies":{"cz-conventional-changelog":"^2.1.0","husky":"^0.14.3","lint-staged":"^7.2.0","semantic-release":"^15.6.0","tap":"^12.0.1","tape":"^4.9.1"},"config":{"commitizen":{"path":"./node_modules/cz-conventional-changelog"}},"gitHead":"d42016427576f0296e90c20a21df6c20d9895eb9","description":"Weave is a system of event driven generic resources and just one possible solution to a list of problems including fault tolerance, load distribution, predictability and scalability for servers that handle data and connect to a database.","_id":"@analogculture/weave@2.0.0","_npmVersion":"5.6.0","_nodeVersion":"10.0.0","_npmUser":{"name":"louisr","email":"louisrudner@gmail.com"},"dist":{"integrity":"sha512-lkBSBNgN7lcTu1HRvMY00mlIUzKMvUkpu6mROTLq4e5uP0JknHoiikpY/tNt3JcQgIakB2k9YTbYZzVp3ymucA==","shasum":"c7006c90944dcad434c91217425f3958e255b88f","tarball":"https://registry.npmjs.org/@analogculture/weave/-/weave-2.0.0.tgz","fileCount":18,"unpackedSize":16773,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbZQ70CRA9TVsSAnZWagAA4LcQAI0iffO5cihjcGt7bZZw\nXOOQBati+mu1uPm4rYJnDjW68G/XccdU0CVLiqjYM3JqqvvOVImewqKnDQD0\nkIIRi4aEKcX6oego3xZTaLu2i9jfnfvNs4GZk7/xpD/7Cd0hLFH1EwGInWhS\nz4DutblXmHkkqMbXxE/m7oCBhETvprmz8o/uin7kvy0jpuMElYKjEEjEnD/7\nRHw2yxY0QS3Hf19XfyKpddxuHNGHxQ5qBiuS8hN9fvKHAFfVqnuR4nYfolOb\nu75+osNDh6qLSIxlPWkJV2kJ4k7GTzcCuNdWJ5m7P/54xL/LOySOh59BSj0W\nqXD47uo9a2FLDxBRpQklOcaSxFom9fvtcjGztpJn1nmMYaqwRyRkngIMzwZK\nXy6qb/WMesuJx+CuYKrQo1Xzjp/CQWIB1YyoVLSQKt4yfUIFwjcPYSHoH9Iw\n7G3S5lMSHYaXzOe8swupgCSw3W8TUkjjYMiqyJeUW3j8u5VOBQAnFECsc+ap\nEAy7SWZ0menkyMzfspSjAZgeQuZZiziROoCxdeSrusAZQRE9FYAAjzHtDtNU\nc8IxNkMciynegv4Uce4o2SP6+ExSi5nQz0O6mERKPB/m7nFoRHzvQ7SyAPzU\nqz0Cz/fBnCkpwldsgBHQ/X3+u8Cz+MGJpOWMwzjLQBeAstPoWOZdbolZwexI\nCx2+\r\n=MKL3\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCID7qWZ6vA8gvoD/Rn1s+UoKPzOesvWciyCcL4JwVCVjrAiAxlbuJb1YhEGNEZthvWEyXL9ZJGK31cu9Id9a9UYHbFg=="}]},"maintainers":[{"email":"louisrudner@gmail.com","name":"louisr"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/weave_2.0.0_1533349619729_0.5869901683724792"},"_hasShrinkwrap":false}},"time":{"created":"2018-06-21T09:34:14.350Z","0.0.1":"2018-06-21T09:34:14.538Z","modified":"2022-04-04T13:53:47.569Z","1.0.0":"2018-07-10T06:22:16.726Z","2.0.0":"2018-08-04T02:26:59.815Z"},"maintainers":[{"email":"louisrudner@gmail.com","name":"louisr"}],"description":"Weave is a system of event driven generic resources and just one possible solution to a list of problems including fault tolerance, load distribution, predictability and scalability for servers that handle data and connect to a database.","license":"MIT","readme":"# Weave\n\nWeave is a system of event driven generic resources and just one possible solution to a list of problems including fault tolerance, load distribution, predictability and scalability for servers that handle data and connect to a database.\n\nUsing weave you can create a horizontally and vertically scalable cluster of workers, which can be used\nto perform generic actions (find, create, update, delete) on an arbitrary number of resources.\n\n## Why use it?\n\nWeave's purpose is simple, to handle database interactions so your servers don't have to.\n\nUse Weave if:\n\n- you want an arbitrarily large number of resources, defined only in your business logic.\n- you want to ensure that queries are always delivered and only delivered once.\n- you want your servers to handle requests and not database interactions.\n- you want a simple way to scale your resource pool.\n\n## How does it work?\n\nA weave service is more like a glorified adapter than a server, it uses AMQP (RabbitMQ) to handle messaging and MongoDB for persistence, you simply pass an action to the worker pool and the first available worker will do the job.\n\nIf you have three separate queries to make, each one will be handled by an async worker and returned. You can await the result before performing the next action or perform them in parallel. A worker can only be given one job at a time and once the job is complete, its current database connection/s will be closed.\n\nThe generic nature of weave means that data sent to a worker is assumed to be \"qualified\", therefor all checks\nfor validation, existence and errors must be made before a call to a weave worker.\n\nWeave uses RabbitMQ's _message acknowledgements_ and _durable messages_ to provide single delivery of messages to any worker in the pool.\n\n## What's in the box?\n\nWeave provides two functions - worker and channel.\n\n### Worker\n\nThe worker function creates a new weave service based on some simple environment variables, this service doesn't require any business logic directly, it simply creates its workers, connects to RabbitMQ and waits for a message.\n\n#### Install/Config\n\n- `npm init --yes`\n- `npm install --save @analogculture/weave`\n- Create a new `.env` file\n- Add following config:\n\n```shell\nCPUS=1\nAPP_NAME=weave_example\nQUEUE_NAME=resource_queue\nMESSAGE_HOST=amqp://localhost:5672\nMONGODB_HOST=mongodb://localhost:27017\n```\n\nNote: you can skip this and use a config object instead.\n\n#### Usage\n\n##### CLI\n\n- Follow the install/config instructions above\n- Create a start script in package.json:\n\n```javascript\n{\n  ...\n  \"scripts\": {\n    \"start\": \"weave\"\n  }\n  ...\n}\n```\n\n##### Programmatic\n\n- Follow the install/config instructions above\n- Create an `index.js` file:\n\n```javascript\nconst { worker } = require('@analogculture/weave')\nworker()\n\n// or with a config object:\n\nworker({\n  cpus: 1,\n  appName: 'weave_example',\n  mongoHost: 'mongodb://localhost:27017',\n  host: 'amqp://localhost:5672',\n  q: 'resource_queue'\n})\n```\n\n### Channel\n\nThe channel function provides a simple API for communicating messages to your Weave pool from any other server or service configured. Configure the message host and queue with environment variables. The API is documented below.\n\n#### Install/Config\n\n- `npm init --yes`\n- `npm install --save @analogculture/weave`\n- Create a new `.env` file\n- Add following config:\n\n```shell\nQUEUE_NAME=resource_queue\nMESSAGE_HOST=amqp://localhost:5672\n```\n\n#### Usage\n\n```javascript\nconst { channel } = require('@analogculture/weave')\n\nconst sendCommand = channel({\n  host: 'amqp://rabbitmq:5672', // defaults to process.env.MESSAGE_HOST\n  queue: 'resource_queue' // defaults to process.env.QUEUE_NAME\n})\n\nconst getItems = async id => {\n  const { data } = await sendCommand({\n    resource: 'items',\n    action: 'find',\n    payload: {\n      entityId: id\n    }\n  })\n  return data[0]\n}\n\ngetItems('abc')\n```\n\n### Details\n\n#### Scaling\n\n#### Vertical Scaling\n\nUnless otherwise specified, on start, a Weave service will automatically detect and scale to create one worker per available CPU core.\n\n#### Horizontal Scaling\n\nGiven the same message host and same queue name, you can replicate the weave service as many times as you like in your cluster and messages will always be handled by single worker processes.\n\n### API Examples / Docs\n\nAPI actions are defined with the worker, the channel merely sends a message with the corresponding data shape.\n\n#### Find\n\n```javascript\nconst { channel } = require('@analogculture/weave')\n\nconst sendCommand = channel({\n  host: 'amqp://rabbitmq:5672',\n  queue: 'resource_queue'\n})\n\nconst { data } = await sendCommand({\n    resource: 'items',\n    action: 'find',\n    payload: {\n      entityId: 'abc'\n    }\n  })\n  return data[0]\n```\n\nYou can include mongodb queries in any call to find eg `payload: { _id: { $in: allocationIds } }`\n\n#### Create\n\n```javascript\nconst { channel } = require('@analogculture/weave')\n\nconst sendCommand = channel({\n  host: 'amqp://rabbitmq:5672',\n  queue: 'resource_queue'\n})\n\nsendCommand({\n  resource: 'items',\n  action: 'create',\n  payload: {\n    data: {\n      name: 'one'\n    },\n    meta: {\n      entityId: 'abc'\n    }\n  }\n})\n```\n\n#### Update\n\n```javascript\nconst { channel } = require('@analogculture/weave')\n\nconst sendCommand = channel({\n  host: 'amqp://rabbitmq:5672',\n  queue: 'resource_queue'\n})\n\nsendCommand({\n  resource: 'items',\n  action: 'update',\n  payload: {\n    data: {\n      name: 'two'\n    },\n    meta: {\n      entityId: 'abc'\n    }\n  }\n})\n```\n","readmeFilename":"readme.md"}