Added mongodb as document store adapter

This commit is contained in:
zneix 2020-08-27 00:42:48 +02:00
parent f3288c4e39
commit bd5c7f9261
4 changed files with 133 additions and 2 deletions

View File

@ -154,6 +154,43 @@ or post.
All of which are optional except `type` with very logical default values.
### MongoDB
To use mongodb storage you must install the 'mongodb' pachage in npm
`npm install mongodb`
Once you've done that, your config section should look like:
``` json
{
"type": "mongodb",
"expire": false,
"connectionUrl": "mongodb://localhost:27017/haste",
"clientOptions": {
"useUnifiedTopology": true,
"useNewUrlParser": true,
"keepAlive": true,
"keepAliveInitialDelay": 60000,
"poolSize": 30,
"socketTimeoutMS": 360000,
"connectTimeoutMS": 360000,
"auth": {
"user": "username",
"password": "password"
},
"authSource": "admin"
}
}
```
You can adjust properties in `clientOptions`, but the ones in config are considered as the most optimal defaults.
You can omit `auth` object if database has no authentication.
No further database configuration is required.
You can set `expire` option to the number of seconds in which documents will expire.
This is set to `false` by default, but will constantly kick back expirations on each view or post.
### Memcached
To use memcache storage you must install the `memcached` package via npm

View File

@ -0,0 +1,94 @@
const winston = require('winston');
const mongodb = require('mongodb');
const MongoDocumentStore = function (config){
this.expire = config.expire;
this.MongoClient = new mongodb.MongoClient(config.connectionUrl, config.clientOptions);
};
MongoDocumentStore.prototype.set = async function (key, data, callback, skipExpire){
winston.silly(`mongo set ${key}`);
const now = Math.floor(Date.now() / 1000);
const that = this;
this.safeConnect(async ( {error} = {} ) => {
if (error) return callback(false);
await this.MongoClient.db().collection('entries').updateOne(
{
'entry_id': key,
$or: [
{ expiration: -1 },
{ expiration: { $gt: now } }
]
},
{
$set: {
'entry_id': key,
value: data,
expiration: that.expire && !skipExpire ? that.expire + now : -1
}
},
{
upsert: true
}
).then((err, result) => {
return callback(true);
})
.catch((err, result) => {
winston.error('error updating mongodb document', { error: err });
return callback(false);
});
});
};
MongoDocumentStore.prototype.get = async function (key, callback, skipExpire){
winston.silly(`mongo get ${key}`);
const now = Math.floor(Date.now() / 1000);
const that = this;
this.safeConnect(async ( {error} = {} ) => {
if (error) return callback(false);
let document = await this.MongoClient.db().collection('entries').findOne({
'entry_id': key,
or: [
{ expiration: -1 },
{ expiration: { $gt: now } }
]
})
.catch(err => {
winston.error('error finding mongodb document', { error: err });
return callback(false);
});
callback(document ? document.value : false);
if (document && document.expiration != -1 && that.expire && !skipExpire){
await this.MongoClient.db().collection('entries').updateOne(
{ 'entry_id': key },
{ $set: { expiration: that.expire + now } }
).catch(err => {
return winston.warn('error extending expiry of mongodb document', { error: err });
});
winston.silly('extended expiry of mongodb document', { key: key, timestamp: that.expire + now })
}
});
};
MongoDocumentStore.prototype.safeConnect = function(cb){
//don't try connecting again if already connected
//https://jira.mongodb.org/browse/NODE-1868
if (this.MongoClient.isConnected()) return cb({error: null});
this.MongoClient.connect()
.then(client => {
winston.debug('connected to mongodb', { success: true });
cb({error: null});
})
.catch(err => {
winston.error('error connecting to mongodb', { error: err });
cb({error: err});
});
};
module.exports = MongoDocumentStore;

2
package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "haste",
"version": "0.2.1",
"version": "0.2.2",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@ -1,6 +1,6 @@
{
"name": "haste",
"version": "0.2.1",
"version": "0.2.2",
"description": "Private Pastebin Server - continued by zneix",
"keywords": [
"paste",