mirror of
https://github.com/wassname/talk.git
synced 2026-06-28 18:45:55 +08:00
82 lines
2.3 KiB
JavaScript
82 lines
2.3 KiB
JavaScript
const Setting = require('../models/setting');
|
|
const { ErrSettingsNotInit } = require('../errors');
|
|
const { dotize } = require('./utils');
|
|
const { isEmpty, zipObject } = require('lodash');
|
|
const DataLoader = require('dataloader');
|
|
|
|
const selector = { id: '1' };
|
|
|
|
async function loadFn(/* fields = [] */) {
|
|
// Originally, we used the projection operation, turns out this isn't that
|
|
// fast. We should utilize the redis cache instead here.
|
|
// const model = await Setting.findOne(selector).select(uniq(fields));
|
|
|
|
const model = await Setting.findOne(selector);
|
|
if (!model) {
|
|
throw new ErrSettingsNotInit();
|
|
}
|
|
|
|
return model.toObject();
|
|
}
|
|
|
|
// batchLoadFn will load a settings object with all the requested fields.
|
|
async function batchLoadFn(fields) {
|
|
// Load a settings object with all the requested fields.
|
|
const obj = await loadFn(fields);
|
|
|
|
// Return the specific fields for each of the fields that were loaded.
|
|
return fields.map(field => obj[field]);
|
|
}
|
|
|
|
// batchedSettingsLoader will load setting fields for each request. This isn't a
|
|
// cached loader, so this is really just for optimizing the requests made to the
|
|
// database by batching.
|
|
const batchedSettingsLoader = new DataLoader(batchLoadFn, { cache: false });
|
|
|
|
class Settings {
|
|
static async retrieve(...fields) {
|
|
if (!isEmpty(fields)) {
|
|
// Included for backwards compatibility.
|
|
return Settings.select(...fields);
|
|
}
|
|
|
|
// Call the loadFn directly if we need to load all the fields.
|
|
return loadFn(fields);
|
|
}
|
|
|
|
static async select(...fields) {
|
|
// Load all the values for the specific fields.
|
|
const values = await batchedSettingsLoader.loadMany(fields);
|
|
|
|
// Zip up the fields and values to create an object to return and return the
|
|
// assembled Settings object.
|
|
return zipObject(fields, values);
|
|
}
|
|
|
|
static async update(settings) {
|
|
const updatedSettings = await Setting.findOneAndUpdate(
|
|
selector,
|
|
{
|
|
$set: dotize(settings),
|
|
},
|
|
{
|
|
upsert: true,
|
|
new: true,
|
|
setDefaultsOnInsert: true,
|
|
}
|
|
);
|
|
|
|
return updatedSettings;
|
|
}
|
|
|
|
static init(defaults = {}) {
|
|
return Settings.retrieve().catch(() => {
|
|
const settings = new Setting(defaults);
|
|
|
|
return settings.save();
|
|
});
|
|
}
|
|
}
|
|
|
|
module.exports = Settings;
|