{"_id":"gig.fs","_rev":"28-405a42e0e56ed4f012830c7f91f85cdd","name":"gig.fs","description":"GiG.fs ======","dist-tags":{"latest":"0.2.5"},"versions":{"0.1.4":{"name":"gig.fs","version":"0.1.4","dependencies":{"express":"3.4.x","async":"0.2.x","mkdirp":"0.3.x","request":"2.34.x","rimraf":"2.2.x"},"main":"./client/index.js","bin":{"table":"./table/table.js","store":"./store/store.js"},"repository":{"type":"git","url":"git://github.com/breach/gig.fs"},"description":"GiG.fs ======","bugs":{"url":"https://github.com/breach/gig.fs/issues"},"_id":"gig.fs@0.1.4","dist":{"shasum":"f1b104ff3886834c69ea02e1b0a4ea040f06c65d","tarball":"https://registry.npmjs.org/gig.fs/-/gig.fs-0.1.4.tgz","integrity":"sha512-FgiVxkSWgK9B8O/3kPHbsvyCK2YQ7LhCPLM8FcV8phdYL3OLoWSlqqQ6H18bmNHSOKsuZwFHP1aoYbEFuxsDtg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFIvjz9QZsTiYGnbXNMT8YUCZlqgqEyj2lMmUeKxi2c+AiAzWXljGspRGSV3f8e4iEtGu6Px2Zdqe1eNrNMi44NgbQ=="}]},"_from":".","_npmVersion":"1.3.11","_npmUser":{"name":"spolu","email":"polu.stanislas@gmail.com"},"maintainers":[{"name":"spolu","email":"polu.stanislas@gmail.com"}]},"0.1.5":{"name":"gig.fs","version":"0.1.5","dependencies":{"express":"3.4.x","async":"0.2.x","mkdirp":"0.3.x","request":"2.34.x","rimraf":"2.2.x"},"main":"./client/index.js","bin":{"table":"./table/table.js","store":"./store/store.js"},"repository":{"type":"git","url":"git://github.com/breach/gig.fs"},"description":"GiG.fs ======","bugs":{"url":"https://github.com/breach/gig.fs/issues"},"_id":"gig.fs@0.1.5","dist":{"shasum":"b9f437fc3024a72afa2717ebff92082d3107ec3b","tarball":"https://registry.npmjs.org/gig.fs/-/gig.fs-0.1.5.tgz","integrity":"sha512-E6MXDZlLCiZuZd39JKXOEC4bXPZs3SUpV6M/QmzbYGVvFw8HUTe9Isz3Q3YX5qB8yBf2av9iWkWdJ/K44+S8ag==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDGpKMGXPXcp4MU0vxZTmnML0sAijKB7frKIRTgic1d7AIhAKpg8pKGb+ijvylbkyv6Ic9kHR56LJH079MPdv585P0N"}]},"_from":".","_npmVersion":"1.3.11","_npmUser":{"name":"spolu","email":"polu.stanislas@gmail.com"},"maintainers":[{"name":"spolu","email":"polu.stanislas@gmail.com"}]},"0.1.6":{"name":"gig.fs","version":"0.1.6","dependencies":{"express":"3.4.x","async":"0.2.x","mkdirp":"0.3.x","request":"2.34.x","rimraf":"2.2.x"},"main":"./client/index.js","bin":{"table":"./table/table.js","store":"./store/store.js"},"repository":{"type":"git","url":"git://github.com/breach/gig.fs"},"description":"GiG.fs ======","bugs":{"url":"https://github.com/breach/gig.fs/issues"},"_id":"gig.fs@0.1.6","dist":{"shasum":"42f4560b768c88479b9413182fd51ca7a319d341","tarball":"https://registry.npmjs.org/gig.fs/-/gig.fs-0.1.6.tgz","integrity":"sha512-qGOBT01ML4K+y8dg59EpC8EwAVhwnlVa1NXV3Ve2W7kmxdkiXfPQW3WP/vCWQ2RvQH4qgNqPe3TBFkYT4H0cwA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGbOEYDIa1rNqd68h/gqlzbZ0YCzNrsX/Go91SQz6iptAiEAy7XD8g/Q3arBdpg7YpgMoytnDCYtk9rKQcmL94zHvs8="}]},"_from":".","_npmVersion":"1.2.32","_npmUser":{"name":"spolu","email":"polu.stanislas@gmail.com"},"maintainers":[{"name":"spolu","email":"polu.stanislas@gmail.com"}]},"0.2.1":{"name":"gig.fs","version":"0.2.1","dependencies":{"express":"3.4.x","async":"0.2.x","mkdirp":"0.3.x","request":"2.34.x","rimraf":"2.2.x"},"main":"./client/index.js","bin":{"table":"./table/table.js","store":"./store/store.js"},"repository":{"type":"git","url":"git://github.com/breach/gig.fs"},"description":"GiG.fs ======","bugs":{"url":"https://github.com/breach/gig.fs/issues"},"_id":"gig.fs@0.2.1","dist":{"shasum":"0b6281c14b72905987876fb45a9531f4d2fc2d21","tarball":"https://registry.npmjs.org/gig.fs/-/gig.fs-0.2.1.tgz","integrity":"sha512-aCGsEcj/lffTk/Ny76OOQeVzpebK/opBnERjVqQsLoT1ZGagSBAHH/alYPCpg0v45DonrSvlOUOot8793u4x/w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICE1kYb2E8DaS4Qa3AIULxmkJ3xcfKlGAjNh9xYKp64uAiBFnuVozGBecQWird9s/gazRUtu1Rm6yqyhulHU800zWA=="}]},"_from":".","_npmVersion":"1.3.11","_npmUser":{"name":"spolu","email":"polu.stanislas@gmail.com"},"maintainers":[{"name":"spolu","email":"polu.stanislas@gmail.com"}]},"0.2.2":{"name":"gig.fs","version":"0.2.2","dependencies":{"express":"3.4.x","async":"0.2.x","mkdirp":"0.3.x","request":"2.34.x","rimraf":"2.2.x"},"main":"./client/index.js","bin":{"table":"./table/table.js","store":"./store/store.js"},"repository":{"type":"git","url":"git://github.com/breach/gig.fs"},"description":"GiG.fs ======","bugs":{"url":"https://github.com/breach/gig.fs/issues"},"_id":"gig.fs@0.2.2","dist":{"shasum":"8663f78c2967c2a0acf8250edf173edce15a240b","tarball":"https://registry.npmjs.org/gig.fs/-/gig.fs-0.2.2.tgz","integrity":"sha512-7vBdYmcW3dFI1gxPel/P52x54SDE71/g5vf+a22nzM+VAdvxoSeJPI5wuHV6AO8aJ8gLAL1KWOyhdyodCn5t5A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFyUN1DdJl1JxWyg5Y27GNyFxyVONt5H08rmeuho7zPmAiBNSzcdcWVFa1WdoZwfJ+pVuHoSxecCgWJLFSPEyMHoYA=="}]},"_from":".","_npmVersion":"1.3.11","_npmUser":{"name":"spolu","email":"polu.stanislas@gmail.com"},"maintainers":[{"name":"spolu","email":"polu.stanislas@gmail.com"}]},"0.2.4":{"name":"gig.fs","version":"0.2.4","dependencies":{"express":"3.4.x","async":"0.2.x","mkdirp":"0.3.x","request":"2.34.x","rimraf":"2.2.x"},"main":"./client/index.js","bin":{"table":"./table/table.js","store":"./store/store.js"},"scripts":{"test":"nodeunit test/test_*"},"repository":{"type":"git","url":"git://github.com/breach/gig.fs"},"description":"GiG.fs ======","bugs":{"url":"https://github.com/breach/gig.fs/issues"},"_id":"gig.fs@0.2.4","dist":{"shasum":"95e8cc3673c5ec4953725d9983628f7e57988bc6","tarball":"https://registry.npmjs.org/gig.fs/-/gig.fs-0.2.4.tgz","integrity":"sha512-gRDshaXa2wX1UGG2i88k4t47rxqA1AD6fhe5IV5poiw93MR/rPbtf7jI792wpRod5rhKHVFM7h22xP+1SiWfTQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGMkPN7M2GoDS1K9SYgvQUZmXkY5BUrHwqgopSTfwt2QAiEA4/1WXVICMKiAFZNNw+AxlD1muiXEHlNLBg48IRjN+oA="}]},"_from":".","_npmVersion":"1.3.11","_npmUser":{"name":"spolu","email":"polu.stanislas@gmail.com"},"maintainers":[{"name":"spolu","email":"polu.stanislas@gmail.com"}]},"0.2.5":{"name":"gig.fs","version":"0.2.5","dependencies":{"express":"3.4.x","async":"0.2.x","mkdirp":"0.3.x","request":"2.34.x","rimraf":"2.2.x"},"main":"./client/index.js","bin":{"table":"./table/table.js","store":"./store/store.js"},"scripts":{"test":"nodeunit test/test_*"},"repository":{"type":"git","url":"git://github.com/breach/gig.fs"},"description":"GiG.fs ======","bugs":{"url":"https://github.com/breach/gig.fs/issues"},"homepage":"https://github.com/breach/gig.fs","_id":"gig.fs@0.2.5","_shasum":"2ec412ad401c659ecca0900041f2f3f2fad1efa6","_from":".","_npmVersion":"1.4.9","_npmUser":{"name":"spolu","email":"polu.stanislas@gmail.com"},"maintainers":[{"name":"spolu","email":"polu.stanislas@gmail.com"}],"dist":{"shasum":"2ec412ad401c659ecca0900041f2f3f2fad1efa6","tarball":"https://registry.npmjs.org/gig.fs/-/gig.fs-0.2.5.tgz","integrity":"sha512-frp/7DBrExBV2cF3g7Guo2hyXeusMsPojVb05XVqGqkkHMyNmwvHHrz5zd2DYc1utAOkBVG+nx4+xGgt0rZEdQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCKKXsleo3MPoLegsHTLu/8bY7nQUn4BCWylfP9CFTpuAIhAOQ4AnMTs9A1gnh+rSn6s0KgI+k3yk2d2Q0an0wNJDZu"}]}}},"readme":"GiG.fs\n======\n\nCentrally Orchestrated Multi Node Log-Based Storage with Distributed Conflict \nResolution\n\nGiG.fs is a log-based multi node storage based on the principle of operation\npropagation and oplog pruning. Operations are pushed to the storage and conflict\nresolution is delegated to the client. Conflict resolution is done by retrieving\nthe different operation logs and replaying them in a merged version.\n\nRead are always first attempted locally (delayed if the data was never retrieved \nyet). A central authority server serves as rendez-vous to retrieve the mount \ntable, that is, the different nodes for each root path, called `channels`.\n\nThe client library only stores data in memory. Tokens have an expiry date. The\nentire system operates on the following asumptions:\n\n- Small amount of data. Holds in memory.\n- Log based with history replay and distributed reconciliation\n- Client nodes store data in memory\n- Writes get commited on network but optimistically accepted. Disconnected OK.\n- Notifications when pathes are modified (local and remote)\n- Temporary keys `{ node, end_time, signature }`\n\nAll calls to the nodes are trackable thanks to the token attached to them.\n\nOPLOG Structure:\n----------------\nThe oplog is an array of operations with the following structure:\n```\n{ \n  date: 12312...\n  sha: a2ef...\n  payload: { ... }\n}\n\n{ \n  date: 12312...\n  sha: a2ef...\n  value: { ... }\n}\n```\nThe `payload` is defined by the user and an operation is always associated with\na type. The user provides reducers per type she uses.\n\nOperations with a `value` field (called `values`) are used to allow the pruning\nof the oplog. Whenever a value is encoutered, history before that value is\nignored by the conflict resolution algorithm.\n\nAn oplog is initialized with a value equal to `null`. \n\nThe oplog is automatically pruned by inserting `values` into it whenever a\nclient considers that all the stores it knows of are in sync. Inserting a value\nmay fail on some stores, but it will eventually get propagated later on by other\nclients to all of the stores upon reconnect.\n\nFinally, stores stream operations they accept so that clients can stay up to\ndate, so that most oplog read happen locally.\n\nSession Tokens:\n---------------\n\n- Sessions are created on the table with a timeout\n- `store_token` are sent to the stores and are generated by the table\n- `store_token` are checked initially by the the store with table and inherit the\n  parent `session_token` timeout\n- Revoking the session on the table will revoke the `store_tokens` on each store\n  as well.\n\nNon-Connected Mode:\n-------------------\nGiG.fs is capable to operate without remote connection. This is done by\nspecifying a `local_table` that gets merged with any remote table found. GiG.fs\ncan entirely operate with solely the local table for fully local operations.\nThe local table specifies the channels where a local store may be participating\nas well as attributes for these stores (`in_memory` or `local_path`);\n```\nlocal_table: {\n  core: [\n    { storage_path: '/home/spolu/...' }\n  ],\n  modules: [\n    { in_memory: true }\n  ]\n}\n```\n\n\nConflict Resolution:\n--------------------\n```\nREAD PATH:\n\nOn each store, Read oplog if not already in memory\nWhen first oplog received\nReduce current value and return\nStore in memory all other oplogs and register to stream\nAttempt syncing and pruning\n\nWRITE PATH:\n\nOn each store, read and then insert op in oplog locally, recompute value\npush op to store\nAttempt syncing and pruning\n\nSYNCING & PRUNING:\n\nOn each store, read oplog\nCompare each store oplogs\nIf discrepancies, push ops to oplogs unaware of them\nOtherwise push a new value to all oplogs for pruning\n\n```\n\nGiG.fs Table\n------------\n\n```\nuser_id -> { \n  master,                                              // hash(user_id, pwd)\n  channel -> [ { id, store_url } ],     \n  [ tokens ]\n};\n\n\n/* ADMIN */\n\n// master\nPUT  /user/:user_id/master/:master                     // revoke all sessions\n\n/* PUBLIC */\n\n// sessions\nGET  /user/:user_id/session/new\n     master, timeout, description\nGET  /user/:user_id/session/all\n     master\nDEL  /user/:user_id/session/:session_token              \nGET  /user/:user_id/session/check/:session_token\n\n// table\nPOST /user/:user_id/table/:channel/store\n     master\n     { store_url, code }\nDEL  /user/:user_id/table/:channel/store/:store_id\n     master\nDEL  /user/:user_id/table/:channel\n     master\nGET  /user/:user_id/table\n     master | session_token\nGET  /user/:user_id/table/:channel\n     master | session_token\nGET  /user/:user_id/table/check/:store_token\n\nStorage:\n- user's master: $GIGFS_DATA/:salt/:user/user.json\n- user's tokens: $GIGFS_DATA/:salt/:user/sessions.json\n- user's table: $GIGFS_DATA/:salt/:user/table.json\n\n```\n\nGiG.fs Store\n------------\n\n```\nuser_id -> {\n  table: { id, table_url }, \n  { path, type } -> { [ op ] },\n}\nop := { date, sha, payload }\n\nBASE_URL = /user/:user_id\n\n/* ADMIN */\n\n// confirmation\nPUT  /admin/user/:user_id\nGET  /admin/user/:user_id/code\n\n/* PUBLIC */\n\n// table confirmation\nPOST {BASE_URL}/confirm\n     { table_url, code }\n\n// store_token\nDEL  {BASE_URL}/session/:store_token\n\n// oplog\nPOST {BASE_URL}/oplog\n     store_token, path, type\n     { date, payload|value, sha }\nGET  {BASE_URL}/oplog\n     store_token, path, type\nGET  {BASE_URL}/oplog/stream\n     store_token, [reg_id]\n\nStorage:\n- user's meta:   $GIGFS_DATA/:salt/:user/user.json\n- user's data:   $GIGFS_DATA/:salt/:user/root/:type/...[path]...\n\nTODO: BLOB Storage\n```\n\nGiG.fs Client\n-------------\n\n```\nvar cli = require('gig.fs').gig({\n  remote_table: { table_url, session_token },\n  local_table: { channel: [ { storage_path } ] } \n});\n\ncli.init(cb_());\ncli.register(type, reduce_fun);\n\ncli.get(channel, type, path, cb_(err, value));\ncli.push(channel, type, path, op, cb_(err, value));\n\ncli.on(channel, type, path, cb_(type, value, [op]));\n\n```\n","maintainers":[{"name":"spolu","email":"polu.stanislas@gmail.com"}],"time":{"modified":"2022-06-18T08:19:16.347Z","created":"2014-04-11T20:40:45.746Z","0.1.4":"2014-04-11T20:40:46.616Z","0.1.5":"2014-04-11T22:23:49.213Z","0.1.6":"2014-04-16T02:23:23.143Z","0.2.1":"2014-05-14T00:33:31.273Z","0.2.2":"2014-05-14T00:36:08.573Z","0.2.4":"2014-05-21T19:18:08.135Z","0.2.5":"2014-06-18T23:49:51.749Z"},"readmeFilename":"README.md","repository":{"type":"git","url":"git://github.com/breach/gig.fs"},"bugs":{"url":"https://github.com/breach/gig.fs/issues"},"homepage":"https://github.com/breach/gig.fs"}