Implement config notification event

Add fieldChanged event to config objects that is triggered when the
value of a field in a group belonging to it is changed.
This commit is contained in:
Hornwitser committed 2020-05-30 14:27:59 +02:00
1 parent fc3686b865
commit 67ca8dcc4d
4 files changed
+101 -21

No files matched your search

+39 -10
View File
@@ -1,6 +1,9 @@
// Configuration classes
"use strict";
const events = require("events");
const util = require("util");
const { basicType } = require("lib/helpers");
@@ -55,10 +58,20 @@ function splitOn(separator, string) {
* Represents a collection of ConfigGroup instances that can be
* managed as one.
*
* This is an EventEmitter with the following events:
* - fieldChanged -
* invoked after a field has been updated in one of the config groups
* belonging to this config. Takes three parameters: group, field,
* prev.
*
* @extends events.EventEmitter
*
* @memberof module:lib/config
*/
class Config {
class Config extends events.EventEmitter {
constructor() {
super();
if (!this.constructor._finalized) {
throw new Error(`Cannot instantiate incomplete Config class ${this.constructor.name}`)
}
@@ -71,7 +84,7 @@ class Config {
for (let [name, GroupClass] of this.constructor._groups) {
if (!this._groups.has(name)) {
let group = new GroupClass();
await group.init();
await group.init(this);
this._groups.set(name, group);
}
}
@@ -98,7 +111,7 @@ class Config {
}
let group = new GroupClass();
await group.load(serializedGroup);
await group.load(this, serializedGroup);
this._groups.set(GroupClass.groupName, group);
}
@@ -123,12 +136,12 @@ class Config {
* Updates all groups in the config with groups in the serialized
* config passed.
*/
update(serializedConfig) {
update(serializedConfig, notify) {
this._validate(serializedConfig);
for (let serializedGroup of serializedConfig.groups) {
let group = this._groups.get(serializedGroup.name);
if (group) {
group.update(serializedGroup);
group.update(serializedGroup, notify);
} else {
this._unknownGroups.set(serializedGroup.name, serializedGroup);
}
@@ -226,6 +239,11 @@ class Config {
/**
* Collection of related config entries
*
* Type checks and stores a collection of related config entries. Attempt
* to set invalid values for fields will result in an error thrown while
* loading a config with invalid values will result in those being replaced
* by the innitial value for those fields.
*
* @memberof module:lib/config
*/
class ConfigGroup {
@@ -242,6 +260,7 @@ class ConfigGroup {
this._fields = new Map();
this._unknownFields = new Map();
this._config = null;
}
/**
@@ -250,7 +269,9 @@ class ConfigGroup {
* Computes and assigns the initial values for all fields of the
* config group.
*/
async init() {
async init(config) {
this._config = config;
for (let [name, def] of this.constructor._definitions) {
if (this._fields.has(name)) {
continue;
@@ -275,9 +296,9 @@ class ConfigGroup {
* group and then initializes any possible missing fields from it to
* their default values.
*/
async load(serializedGroup) {
this.update(serializedGroup);
await this.init();
async load(config, serializedGroup) {
this.update(serializedGroup, false);
await this.init(config);
}
/**
@@ -345,7 +366,11 @@ class ConfigGroup {
}
}
let prev = this._fields.get(name);
this._fields.set(name, value);
if (this._config && !util.isDeepStrictEqual(value, prev)) {
this._config.emit("fieldChanged", this, name, prev);
}
}
/**
@@ -354,7 +379,7 @@ class ConfigGroup {
* Overwrites the values of all the fields in this config group that
* has a valid value in the passed serialized group with that value.
*/
update(serializedGroup) {
update(serializedGroup, notify) {
if (basicType(serializedGroup) !== "object") {
throw new Error(`Expected object, not ${basicType(serializedGroup)} for ConfigGroup`);
}
@@ -388,7 +413,11 @@ class ConfigGroup {
continue;
}
let prev = this._fields.get(name);
this._fields.set(name, value);
if (notify && this._config && !util.isDeepStrictEqual(value, prev)) {
this._config.emit("fieldChanged", this, name, prev);
}
}
}
+13
View File
@@ -42,6 +42,19 @@ class BaseInstancePlugin {
*/
async init() { }
/**
* Called when the value of a config field changed.
*
* Invoked after the value of the config field given by `field` has
* changed.
*
* @param {module:lib/config.ConfigGroup} group -
* The group who's field got changed on.
* @param {string} field - Name of the field that changed.
* @param prev - The previous value of the field.
*/
async onInstanceConfigFieldChanged(group, field, prev) { }
/**
* Called before collecting Prometheus metrics
*