diff --git a/README.md b/README.md index 1cb06f7..98bc508 100644 --- a/README.md +++ b/README.md @@ -198,6 +198,22 @@ Also, you must create an `uploads` table, which will store all the data for uplo You can optionally add the `user` and `password` properties to use a user system. +### Google Datastore + +To use the Google Datastore storage system, you must install the `@google-cloud/datastore` package via npm + +`npm install @google-cloud/datastore` + +Once you've done that, your config section should look like this: + +``` json +{ + "type": "google-datastore" +} +``` + +Authentication is handled automatically by [Google Cloud service account credentials](https://cloud.google.com/docs/authentication/getting-started), by providing authentication details to the GOOGLE_APPLICATION_CREDENTIALS environmental variable. + ### Amazon S3 To use [Amazon S3](https://aws.amazon.com/s3/) as a storage system, you must @@ -316,8 +332,6 @@ Here is a list of all the environment variables | RATELIMITS_BLACKLIST_EVERY_SECONDS | | By default client names in the blacklist will be subject to 0 requests per hours | | RATELIMITS_BLACKLIST | example1.blacklist,example2.blacklist | Comma separated list of the clients which are in the blacklistpool. | - - ## Author John Crepezzi diff --git a/lib/document_stores/google-datastore.js b/lib/document_stores/google-datastore.js new file mode 100644 index 0000000..76fc827 --- /dev/null +++ b/lib/document_stores/google-datastore.js @@ -0,0 +1,89 @@ +/*global require,module,process*/ + +const Datastore = require('@google-cloud/datastore'); +const winston = require('winston'); + +class GoogleDatastoreDocumentStore { + + // Create a new store with options + constructor(options) { + this.kind = "Haste"; + this.expire = options.expire; + this.datastore = new Datastore(); + } + + // Save file in a key + set(key, data, callback, skipExpire) { + var expireTime = (skipExpire || this.expire === undefined) ? null : new Date(Date.now() + this.expire * 1000); + + var taskKey = this.datastore.key([this.kind, key]) + var task = { + key: taskKey, + data: [ + { + name: 'value', + value: data, + excludeFromIndexes: true + }, + { + name: 'expiration', + value: expireTime + } + ] + }; + + this.datastore.insert(task).then(() => { + callback(true); + }) + .catch(err => { + callback(false); + }); + } + + // Get a file from a key + get(key, callback, skipExpire) { + var taskKey = this.datastore.key([this.kind, key]) + + this.datastore.get(taskKey).then((entity) => { + if (skipExpire || entity[0]["expiration"] == null) { + callback(entity[0]["value"]); + } + else { + // check for expiry + if (entity[0]["expiration"] < new Date()) { + winston.info("document expired", {key: key, expiration: entity[0]["expiration"], check: new Date(null)}); + callback(false); + } + else { + // update expiry + var task = { + key: taskKey, + data: [ + { + name: 'value', + value: entity[0]["value"], + excludeFromIndexes: true + }, + { + name: 'expiration', + value: new Date(Date.now() + this.expire * 1000) + } + ] + }; + this.datastore.update(task).then(() => { + }) + .catch(err => { + winston.error("failed to update expiration", {error: err}); + }); + callback(entity[0]["value"]); + } + } + }) + .catch(err => { + winston.error("Error retrieving value from Google Datastore", {error: err}); + callback(false); + }); + } +} + +module.exports = GoogleDatastoreDocumentStore;