IGNITE-11386 Web console: Actualized cluster configuration.
diff --git a/backend/app/schemas.js b/backend/app/schemas.js
index 65d4b93..a2fad1c 100644
--- a/backend/app/schemas.js
+++ b/backend/app/schemas.js
@@ -1237,6 +1237,10 @@
className: String
}
},
+ localEventListeners: [{
+ className: String,
+ eventTypes: [String]
+ }],
mvccVacuumThreadCount: Number,
mvccVacuumFrequency: Number,
authenticationEnabled: Boolean,
diff --git a/frontend/app/configuration/components/page-configure-advanced/components/cluster-edit-form/controller.ts b/frontend/app/configuration/components/page-configure-advanced/components/cluster-edit-form/controller.ts
index 3a2c8bf..1de84ab 100644
--- a/frontend/app/configuration/components/page-configure-advanced/components/cluster-edit-form/controller.ts
+++ b/frontend/app/configuration/components/page-configure-advanced/components/cluster-edit-form/controller.ts
@@ -82,12 +82,25 @@
this.eventStorage.push({value: null, label: 'Disabled'});
this.eventGroups = _.filter(this.IgniteEventGroups, ({value}) => value !== 'EVTS_SWAPSPACE');
+
+ _.forEach(this.eventGroups, (grp) => grp.events = _.filter(grp.events, (evt) => evt.indexOf('SWAP') < 0));
}
else {
this.eventGroups = this.IgniteEventGroups;
this.marshallerVariant.splice(0, 0, {value: 'OptimizedMarshaller', label: 'OptimizedMarshaller'});
}
+
+ this.eventTypes = [];
+
+ _.forEach(this.eventGroups, (grp) => {
+ _.forEach(grp.events, (e) => {
+ const newVal = {value: e, label: e};
+
+ if (!_.find(this.eventTypes, newVal))
+ this.eventTypes.push(newVal);
+ });
+ });
};
rebuildDropdowns();
diff --git a/frontend/app/configuration/components/page-configure-advanced/components/cluster-edit-form/templates/events.pug b/frontend/app/configuration/components/page-configure-advanced/components/cluster-edit-form/templates/events.pug
index e422462..12219fe 100644
--- a/frontend/app/configuration/components/page-configure-advanced/components/cluster-edit-form/templates/events.pug
+++ b/frontend/app/configuration/components/page-configure-advanced/components/cluster-edit-form/templates/events.pug
@@ -109,5 +109,43 @@
tip: 'Array of event types, which will be recorded by GridEventStorageManager#record(Event)<br/>\
Note, that either the include event types or the exclude event types can be established'
})
+ .pc-form-grid-col-60
+ .ignite-form-field
+ +form-field__label({label: 'Local event listeners:', name: '"LocalEventListeners"'})
+ +form-field__tooltip({title: `Local event listeners`})
+
+ -var items = model + '.localEventListeners'
+ list-editable.pc-list-editable-with-form-grid(ng-model=items name='LocalEventListeners')
+ list-editable-item-edit.pc-form-grid-row
+ - form = '$parent.form'
+ .pc-form-grid-col-40
+ +form-field__java-class({
+ label: 'Listener class name:',
+ model: '$item.className',
+ name: '"EventListenerClassName"',
+ required: true,
+ tip: 'Local event listener implementation class name',
+ validationActive: true
+ })
+ .pc-form-grid-col-20
+ +form-field__dropdown({
+ label: 'Event types:',
+ model: '$item.eventTypes',
+ name: '"EventLisneterEventTypes"',
+ required: true,
+ multiple: true,
+ placeholder: 'Choose event types',
+ placeholderEmpty: '',
+ options: '$ctrl.eventTypes',
+ tip: 'Listened event types:'
+ })
+ list-editable-no-items
+ list-editable-add-item-button(
+ add-item=`$ctrl.Clusters.addLocalEventListener($ctrl.clonedCluster)`
+ label-single='listener'
+ label-multiple='listeners'
+ )
+
+ - form = 'events'
.pca-form-column-6
+preview-xml-java(model, 'clusterEvents')
diff --git a/frontend/app/configuration/generator/generator/Beans.js b/frontend/app/configuration/generator/generator/Beans.js
index e4f9001..02f6015 100644
--- a/frontend/app/configuration/generator/generator/Beans.js
+++ b/frontend/app/configuration/generator/generator/Beans.js
@@ -378,8 +378,11 @@
keyClsName: dflt.keyClsName,
keyField: dflt.keyField || 'name',
valClsName: dflt.valClsName,
+ valClsNameShow: dflt.valClsNameShow,
valField: dflt.valField || 'value',
- entries
+ entries,
+ keyClsGenericType: dflt.keyClsGenericType,
+ isKeyClsGenericTypeExtended: dflt.isKeyClsGenericTypeExtended
});
}
diff --git a/frontend/app/configuration/generator/generator/ConfigurationGenerator.js b/frontend/app/configuration/generator/generator/ConfigurationGenerator.js
index bb2d98f..07d3e79 100644
--- a/frontend/app/configuration/generator/generator/ConfigurationGenerator.js
+++ b/frontend/app/configuration/generator/generator/ConfigurationGenerator.js
@@ -1241,6 +1241,13 @@
}
}
+ cfg.mapProperty('localEventListeners', _.map(cluster.localEventListeners,
+ (lnr) => ({className: new EmptyBean(lnr.className), eventTypes: _.map(lnr.eventTypes, (evt) => {
+ const grp = _.find(this.eventGrps, ((grp) => grp.events.indexOf(evt) >= 0));
+
+ return {class: grp.class, label: evt};
+ })})), 'localEventListeners');
+
return cfg;
}
diff --git a/frontend/app/configuration/generator/generator/JavaTransformer.service.js b/frontend/app/configuration/generator/generator/JavaTransformer.service.js
index 25a9760..ec60b74 100644
--- a/frontend/app/configuration/generator/generator/JavaTransformer.service.js
+++ b/frontend/app/configuration/generator/generator/JavaTransformer.service.js
@@ -386,6 +386,12 @@
static _toObject(clsName, val) {
const items = _.isArray(val) ? val : [val];
+ if (clsName === 'EVENTS') {
+ const lastIdx = items.length - 1;
+
+ return [..._.map(items, (v, idx) => (idx === 0 ? 'new int[] {' : ' ') + v.label + (lastIdx === idx ? '}' : ''))];
+ }
+
return _.map(items, (item) => {
if (_.isNil(item))
return 'null';
@@ -520,9 +526,14 @@
const keyClsName = this.javaTypes.shortClassName(map.keyClsName);
const valClsName = this.javaTypes.shortClassName(map.valClsName);
+ const genericTypeShort = map.keyClsGenericType ? this.javaTypes.shortClassName(map.keyClsGenericType) : '';
+ const keyClsGeneric = map.keyClsGenericType ?
+ map.isKeyClsGenericTypeExtended ? `<? extends ${genericTypeShort}>` : `<${genericTypeShort}>`
+ : '';
+
const mapClsName = map.ordered ? 'LinkedHashMap' : 'HashMap';
- const type = `${mapClsName}<${keyClsName}, ${valClsName}>`;
+ const type = `${mapClsName}<${keyClsName}${keyClsGeneric}, ${valClsName}>`;
sb.append(`${this.varInit(type, map.id, vars)} = new ${mapClsName}<>();`);
@@ -546,7 +557,7 @@
sb.append(`${map.id}.put(${key}, ${this._toObject(map.valClsName, _.head(val))});`);
}
else
- sb.append(`${map.id}.put(${key}, ${this._toObject(map.valClsName, val)});`);
+ sb.append(`${map.id}.put(${key}, ${this._toObject(map.valClsNameShow || map.valClsName, val)});`);
});
}
@@ -738,6 +749,9 @@
imports.push(prop.keyClsName);
imports.push(prop.valClsName);
+ if (prop.keyClsGenericType)
+ imports.push(prop.keyClsGenericType);
+
return imports;
}
@@ -853,6 +867,15 @@
break;
+ case 'MAP':
+ if (prop.valClsNameShow === 'EVENTS') {
+ _.forEach(prop.entries, (lnr) => {
+ _.forEach(lnr.eventTypes, (type) => imports.push(`${type.class}.${type.label}`));
+ });
+ }
+
+ break;
+
default:
// No-op.
}
diff --git a/frontend/app/configuration/generator/generator/SpringTransformer.service.js b/frontend/app/configuration/generator/generator/SpringTransformer.service.js
index 5d90ed4..1424c4c 100644
--- a/frontend/app/configuration/generator/generator/SpringTransformer.service.js
+++ b/frontend/app/configuration/generator/generator/SpringTransformer.service.js
@@ -89,8 +89,13 @@
sb.endBlock('</bean>');
}
- static _toObject(clsName, items) {
- return _.map(_.isArray(items) ? items : [items], (item) => {
+ static _toObject(clsName, val) {
+ const items = _.isArray(val) ? val : [val];
+
+ if (clsName === 'EVENTS')
+ return ['<list>', ..._.map(items, (item) => ` <util:constant static-field="${item.class}.${item.label}"/>`), '</list>'];
+
+ return _.map(items, (item) => {
switch (clsName) {
case 'PROPERTY':
case 'PROPERTY_CHAR':
@@ -154,12 +159,16 @@
sb.append(this._toObject(map.keyClsName, key));
sb.endBlock('</key>');
- sb.startBlock('<value>');
+ if (!_.isArray(val))
+ sb.startBlock('<value>');
+
if (isValBean)
this.appendBean(sb, val);
else
- sb.append(this._toObject(map.valClsName, val));
- sb.endBlock('</value>');
+ sb.append(this._toObject(map.valClsNameShow || map.valClsName, val));
+
+ if (!_.isArray(val))
+ sb.endBlock('</value>');
sb.endBlock('</entry>');
}
diff --git a/frontend/app/configuration/generator/generator/defaults/Cluster.service.js b/frontend/app/configuration/generator/generator/defaults/Cluster.service.js
index af5d111..76e9671 100644
--- a/frontend/app/configuration/generator/generator/defaults/Cluster.service.js
+++ b/frontend/app/configuration/generator/generator/defaults/Cluster.service.js
@@ -452,6 +452,15 @@
failureHandler: {
ignoredFailureTypes: {clsName: 'org.apache.ignite.failure.FailureType'}
},
+ localEventListeners: {
+ keyClsName: 'org.apache.ignite.lang.IgnitePredicate',
+ keyClsGenericType: 'org.apache.ignite.events.Event',
+ isKeyClsGenericTypeExtended: true,
+ valClsName: 'int[]',
+ valClsNameShow: 'EVENTS',
+ keyField: 'className',
+ valField: 'eventTypes'
+ },
authenticationEnabled: false,
sqlQueryHistorySize: 1000,
allSegmentationResolversPassRequired: true,
diff --git a/frontend/app/configuration/services/Clusters.ts b/frontend/app/configuration/services/Clusters.ts
index 1e478ed..5aaa3f1 100644
--- a/frontend/app/configuration/services/Clusters.ts
+++ b/frontend/app/configuration/services/Clusters.ts
@@ -587,4 +587,15 @@
cluster.binaryConfiguration.typeConfigurations.push(item);
return item;
}
+
+ addLocalEventListener(cluster) {
+ if (!cluster.localEventListeners)
+ cluster.localEventListeners = [];
+
+ const item = {_id: ObjectID.generate()};
+
+ cluster.localEventListeners.push(item);
+
+ return item;
+ }
}