use of org.openremote.container.persistence.PersistenceEvent in project openremote by openremote.
the class AgentService method configure.
@Override
public void configure() throws Exception {
from(PERSISTENCE_TOPIC).routeId("AgentPersistenceChanges").filter(isPersistenceEventForEntityType(Asset.class)).process(exchange -> {
PersistenceEvent persistenceEvent = exchange.getIn().getBody(PersistenceEvent.class);
Asset asset = (Asset) persistenceEvent.getEntity();
if (isPersistenceEventForAssetType(AGENT).matches(exchange)) {
processAgentChange(asset, persistenceEvent);
} else {
processAssetChange(asset, persistenceEvent);
}
});
// A protocol wants to write a new sensor value
from(SENSOR_QUEUE).routeId("FromSensorUpdates").filter(body().isInstanceOf(AttributeEvent.class)).setHeader(HEADER_SOURCE, () -> SENSOR).to(ASSET_QUEUE);
}
use of org.openremote.container.persistence.PersistenceEvent in project openremote by openremote.
the class RulesService method processAssetChange.
protected void processAssetChange(ServerAsset asset, PersistenceEvent persistenceEvent) {
withLock(getClass().getSimpleName() + "::processAssetChange", () -> {
// We must load the asset from database (only when required), as the
// persistence event might not contain a completely loaded asset
BiFunction<Asset, AssetAttribute, AssetState> buildAssetState = (loadedAsset, attribute) -> new AssetState(loadedAsset, attribute.deepCopy(), Source.INTERNAL);
switch(persistenceEvent.getCause()) {
case INSERT:
// New asset has been created so get attributes that have RULE_STATE meta
List<AssetAttribute> ruleStateAttributes = asset.getAttributesStream().filter(AssetAttribute::isRuleState).collect(Collectors.toList());
// Build an update with a fully loaded asset
ruleStateAttributes.forEach(attribute -> {
ServerAsset loadedAsset = assetStorageService.find(asset.getId(), true);
// If the asset is now gone it was deleted immediately after being inserted, nothing more to do
if (loadedAsset == null)
return;
AssetState assetState = buildAssetState.apply(loadedAsset, attribute);
LOG.fine("Asset was persisted (" + persistenceEvent.getCause() + "), inserting fact: " + assetState);
updateAssetState(assetState, true, true);
});
break;
case UPDATE:
int attributesIndex = Arrays.asList(persistenceEvent.getPropertyNames()).indexOf("attributes");
if (attributesIndex < 0) {
return;
}
// Fully load the asset
final Asset loadedAsset = assetStorageService.find(asset.getId(), true);
// If the asset is now gone it was deleted immediately after being updated, nothing more to do
if (loadedAsset == null)
return;
// Attributes have possibly changed so need to compare old and new attributes
// to determine which facts to retract and which to insert
List<AssetAttribute> oldRuleStateAttributes = attributesFromJson((ObjectValue) persistenceEvent.getPreviousState()[attributesIndex], asset.getId()).filter(AssetAttribute::isRuleState).collect(Collectors.toList());
List<AssetAttribute> newRuleStateAttributes = attributesFromJson((ObjectValue) persistenceEvent.getCurrentState()[attributesIndex], asset.getId()).filter(AssetAttribute::isRuleState).collect(Collectors.toList());
// Retract facts for attributes that are obsolete
getAddedOrModifiedAttributes(newRuleStateAttributes, oldRuleStateAttributes, key -> key.equals(VALUE_TIMESTAMP_FIELD_NAME)).forEach(obsoleteFactAttribute -> {
AssetState update = buildAssetState.apply(loadedAsset, obsoleteFactAttribute);
LOG.fine("Asset was persisted (" + persistenceEvent.getCause() + "), retracting: " + update);
retractAssetState(update);
});
// Insert facts for attributes that are new
getAddedOrModifiedAttributes(oldRuleStateAttributes, newRuleStateAttributes, key -> key.equals(VALUE_TIMESTAMP_FIELD_NAME)).forEach(newFactAttribute -> {
AssetState assetState = buildAssetState.apply(loadedAsset, newFactAttribute);
LOG.fine("Asset was persisted (" + persistenceEvent.getCause() + "), updating: " + assetState);
updateAssetState(assetState, true, true);
});
break;
case DELETE:
// Retract any facts that were associated with this asset
asset.getAttributesStream().filter(AssetAttribute::isRuleState).forEach(attribute -> {
// We can't load the asset again (it was deleted), so don't use buildAssetState() and
// hope that the path of the event asset has been loaded before deletion, although it is
// "unlikely" anybody will access it during retraction...
AssetState assetState = new AssetState(asset, attribute, Source.INTERNAL);
LOG.fine("Asset was persisted (" + persistenceEvent.getCause() + "), retracting fact: " + assetState);
retractAssetState(assetState);
});
break;
}
});
}
use of org.openremote.container.persistence.PersistenceEvent in project openremote by openremote.
the class RulesService method configure.
@Override
public void configure() throws Exception {
// If any ruleset was modified in the database then check its' status and undeploy, deploy, or update it
from(PERSISTENCE_TOPIC).routeId("RulesetPersistenceChanges").filter(isPersistenceEventForEntityType(Ruleset.class)).process(exchange -> {
PersistenceEvent persistenceEvent = exchange.getIn().getBody(PersistenceEvent.class);
processRulesetChange((Ruleset) persistenceEvent.getEntity(), persistenceEvent.getCause());
});
// If any tenant was modified in the database then check its' status and undeploy, deploy or update any
// associated rulesets
from(PERSISTENCE_TOPIC).routeId("RuleEngineTenantChanges").filter(isPersistenceEventForEntityType(Tenant.class)).process(exchange -> {
PersistenceEvent persistenceEvent = exchange.getIn().getBody(PersistenceEvent.class);
Tenant tenant = (Tenant) persistenceEvent.getEntity();
processTenantChange(tenant, persistenceEvent.getCause());
});
// If any asset was modified in the database, detect changed attributes
from(PERSISTENCE_TOPIC).routeId("RuleEngineAssetChanges").filter(isPersistenceEventForEntityType(Asset.class)).process(exchange -> {
PersistenceEvent persistenceEvent = exchange.getIn().getBody(PersistenceEvent.class);
final ServerAsset eventAsset = (ServerAsset) persistenceEvent.getEntity();
processAssetChange(eventAsset, persistenceEvent);
});
}
use of org.openremote.container.persistence.PersistenceEvent in project openremote by openremote.
the class ManagerKeycloakIdentityProvider method publishModification.
protected void publishModification(PersistenceEvent.Cause cause, Tenant tenant) {
// Fire persistence event although we don't use database for Tenant CUD but call Keycloak API
PersistenceEvent persistenceEvent = new PersistenceEvent<>(cause, tenant, new String[0], null);
messageBrokerService.getProducerTemplate().sendBodyAndHeader(PersistenceEvent.PERSISTENCE_TOPIC, ExchangePattern.InOnly, persistenceEvent, PersistenceEvent.HEADER_ENTITY_TYPE, persistenceEvent.getEntity().getClass());
clientEventService.publishEvent(new AssetTreeModifiedEvent(timerService.getCurrentTimeMillis(), tenant.getId(), null));
}
use of org.openremote.container.persistence.PersistenceEvent in project openremote by openremote.
the class AgentService method processAssetChange.
/**
* Looks for new, modified and obsolete AGENT_LINK attributes and links / unlinks them
* with the protocol
*/
protected void processAssetChange(Asset asset, PersistenceEvent persistenceEvent) {
LOG.finest("Processing asset persistence event: " + persistenceEvent.getCause());
switch(persistenceEvent.getCause()) {
case INSERT:
// Asset insert persistence events can be fired before the agent insert persistence event
// so need to check that all protocol configs exist - any that don't we will exclude here
// and handle in agent insert
// If an agent insert just occurred then we will end up trying to link the attribute again
// so we keep track of linked attributes to avoid this
// Link any AGENT_LINK attributes to their referenced protocol
Map<AssetAttribute, List<AssetAttribute>> groupedAgentLinksAttributes = getGroupedAgentLinkAttributes(asset.getAttributesStream(), attribute -> true, attribute -> LOG.warning("Linked protocol configuration not found: " + attribute));
groupedAgentLinksAttributes.forEach(this::linkAttributes);
break;
case UPDATE:
List<String> propertyNames = Arrays.asList(persistenceEvent.getPropertyNames());
// Check if attributes of the asset have been modified
int attributesIndex = propertyNames.indexOf("attributes");
if (attributesIndex < 0) {
return;
}
// Attributes have possibly changed so need to compare old and new state to determine any changes to
// AGENT_LINK attributes
List<AssetAttribute> oldAgentLinkedAttributes = attributesFromJson((ObjectValue) persistenceEvent.getPreviousState()[attributesIndex], asset.getId()).filter(AgentLink::hasAgentLink).collect(Collectors.toList());
List<AssetAttribute> newAgentLinkedAttributes = attributesFromJson((ObjectValue) persistenceEvent.getCurrentState()[attributesIndex], asset.getId()).filter(AgentLink::hasAgentLink).collect(Collectors.toList());
// Unlink thing attributes that are in old but not in new
getGroupedAgentLinkAttributes(getAddedOrModifiedAttributes(newAgentLinkedAttributes, oldAgentLinkedAttributes, key -> key.equals(VALUE_TIMESTAMP_FIELD_NAME)), attribute -> true).forEach(this::unlinkAttributes);
// Link thing attributes that are in new but not in old
getGroupedAgentLinkAttributes(getAddedOrModifiedAttributes(oldAgentLinkedAttributes, newAgentLinkedAttributes, key -> key.equals(VALUE_TIMESTAMP_FIELD_NAME)), attribute -> true, attribute -> LOG.warning("Linked protocol configuration not found: " + attribute)).forEach(this::linkAttributes);
break;
case DELETE:
{
// Unlink any AGENT_LINK attributes from the referenced protocol
Map<AssetAttribute, List<AssetAttribute>> groupedAgentLinkAndProtocolAttributes = getGroupedAgentLinkAttributes(asset.getAttributesStream(), attribute -> true);
groupedAgentLinkAndProtocolAttributes.forEach(this::unlinkAttributes);
break;
}
}
}
Aggregations