mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2025-02-04 13:01:10 +08:00
5beb1bf619
* Update Configuration to handle arrays * Add new db client * Add comment
116 lines
3.3 KiB
JavaScript
116 lines
3.3 KiB
JavaScript
const _ = require("lodash");
|
|
const db = require("../init/db");
|
|
const BASE_CONFIGURATION = require("../constants/base-configuration");
|
|
const Logger = require("../handlers/logger.js");
|
|
|
|
const CONFIG_UPDATE_INTERVAL = 10 * 60 * 1000; // 10 Minutes
|
|
|
|
function mergeConfigurations(baseConfiguration, liveConfiguration) {
|
|
if (
|
|
!_.isPlainObject(baseConfiguration) ||
|
|
!_.isPlainObject(liveConfiguration)
|
|
) {
|
|
return;
|
|
}
|
|
|
|
function merge(base, source) {
|
|
const commonKeys = _.intersection(_.keys(base), _.keys(source));
|
|
|
|
commonKeys.forEach((key) => {
|
|
const baseValue = base[key];
|
|
const sourceValue = source[key];
|
|
|
|
const isBaseValueObject = _.isPlainObject(baseValue);
|
|
const isSourceValueObject = _.isPlainObject(sourceValue);
|
|
const isBaseValueArray = _.isArray(baseValue);
|
|
const isSourceValueArray = _.isArray(sourceValue);
|
|
|
|
const arrayObjectMismatch =
|
|
(isBaseValueObject && isSourceValueArray) ||
|
|
(isBaseValueArray && isSourceValueObject);
|
|
|
|
if (isBaseValueObject && isSourceValueObject) {
|
|
merge(baseValue, sourceValue);
|
|
} else if (
|
|
typeof baseValue === typeof sourceValue &&
|
|
!arrayObjectMismatch // typeof {} = "object", typeof [] = "object"
|
|
) {
|
|
base[key] = sourceValue;
|
|
}
|
|
});
|
|
}
|
|
|
|
merge(baseConfiguration, liveConfiguration);
|
|
}
|
|
|
|
class ConfigurationDAO {
|
|
static configuration = BASE_CONFIGURATION;
|
|
static lastFetchTime = 0;
|
|
static databaseConfigurationUpdated = false;
|
|
|
|
static async getCachedConfiguration(attemptCacheUpdate = false) {
|
|
if (
|
|
attemptCacheUpdate &&
|
|
this.lastFetchTime < Date.now() - CONFIG_UPDATE_INTERVAL
|
|
) {
|
|
Logger.log("stale_configuration", "Cached configuration is stale.");
|
|
return await this.getLiveConfiguration();
|
|
}
|
|
return this.configuration;
|
|
}
|
|
|
|
static async getLiveConfiguration() {
|
|
this.lastFetchTime = Date.now();
|
|
|
|
const configurationCollection = db.collection("configuration");
|
|
|
|
try {
|
|
const liveConfiguration = await configurationCollection.findOne();
|
|
|
|
if (liveConfiguration) {
|
|
const baseConfiguration = _.cloneDeep(BASE_CONFIGURATION);
|
|
mergeConfigurations(baseConfiguration, liveConfiguration);
|
|
|
|
this.pushConfiguration(baseConfiguration);
|
|
this.configuration = Object.freeze(baseConfiguration);
|
|
} else {
|
|
await configurationCollection.insertOne(
|
|
Object.assign({}, BASE_CONFIGURATION)
|
|
); // Seed the base configuration.
|
|
}
|
|
|
|
Logger.log(
|
|
"fetch_configuration_success",
|
|
"Successfully fetched live configuration."
|
|
);
|
|
} catch (error) {
|
|
Logger.log(
|
|
"fetch_configuration_failure",
|
|
`Could not fetch configuration: ${error.message}`
|
|
);
|
|
}
|
|
|
|
return this.configuration;
|
|
}
|
|
|
|
static async pushConfiguration(configuration) {
|
|
if (this.databaseConfigurationUpdated) {
|
|
return;
|
|
}
|
|
|
|
const configurationCollection = db.collection("configuration");
|
|
|
|
try {
|
|
await configurationCollection.replaceOne({}, configuration);
|
|
|
|
this.databaseConfigurationUpdated = true;
|
|
} catch (error) {
|
|
Logger.log(
|
|
"push_configuration_failure",
|
|
`Could not push configuration: ${error.message}`
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = ConfigurationDAO;
|