From dbef320931fbde896ce4a3165d4ce3be18330c6e Mon Sep 17 00:00:00 2001 From: nprentza Date: Mon, 31 Jul 2023 18:48:01 +0300 Subject: [PATCH 1/7] PersistenceObjectStrategy option, basic test 'insert-failover-shouldFireRules' --- .../core/ReliableNamedEntryPoint.java | 3 +- .../core/SerializableStoredObject.java | 2 +- .../core/SerializableStoredRefObject.java | 39 +++++++++ .../SimpleReliableObjectStoreFactory.java | 3 +- ...impleSerializationReliableObjectStore.java | 12 +-- ...rializationReliableObjectStoreFactory.java | 9 ++ ...leSerializationReliableRefObjectStore.java | 86 ++++++++++++++++++ ...eInfinispanReliableObjectStoreFactory.java | 14 ++- .../test/ReliabilityFireAndAlarmTest.java | 87 +++++++++++++++++++ .../test/ReliabilityTestBasics.java | 37 ++++++-- .../org/test/domain/fireandalarm/Alarm.java | 6 ++ .../org/test/domain/fireandalarm/Fire.java | 21 +++++ .../org/test/domain/fireandalarm/Room.java | 27 ++++++ .../test/domain/fireandalarm/Sprinkler.java | 35 ++++++++ .../runtime/conf/PersistedSessionOption.java | 13 +++ 15 files changed, 373 insertions(+), 21 deletions(-) create mode 100644 drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SerializableStoredRefObject.java create mode 100644 drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableRefObjectStore.java create mode 100644 drools-reliability/drools-reliability-tests/src/test/java/org/drools/reliability/test/ReliabilityFireAndAlarmTest.java create mode 100644 drools-reliability/drools-reliability-tests/src/test/java/org/test/domain/fireandalarm/Alarm.java create mode 100644 drools-reliability/drools-reliability-tests/src/test/java/org/test/domain/fireandalarm/Fire.java create mode 100644 drools-reliability/drools-reliability-tests/src/test/java/org/test/domain/fireandalarm/Room.java create mode 100644 drools-reliability/drools-reliability-tests/src/test/java/org/test/domain/fireandalarm/Sprinkler.java diff --git a/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/ReliableNamedEntryPoint.java b/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/ReliableNamedEntryPoint.java index d747a504051..9f9ae720ea6 100644 --- a/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/ReliableNamedEntryPoint.java +++ b/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/ReliableNamedEntryPoint.java @@ -33,7 +33,8 @@ public ReliableNamedEntryPoint(EntryPointId entryPoint, EntryPointNode entryPoin protected ObjectStore createObjectStore(EntryPointId entryPoint, RuleBaseConfiguration conf, ReteEvaluator reteEvaluator) { boolean storesOnlyStrategy = reteEvaluator.getSessionConfiguration().getPersistedSessionOption().getPersistenceStrategy() == PersistedSessionOption.PersistenceStrategy.STORES_ONLY; return storesOnlyStrategy ? - SimpleReliableObjectStoreFactory.get().createSimpleReliableObjectStore(StorageManagerFactory.get().getStorageManager().getOrCreateStorageForSession(reteEvaluator, "ep" + getEntryPointId())) : + SimpleReliableObjectStoreFactory.get().createSimpleReliableObjectStore(StorageManagerFactory.get().getStorageManager().getOrCreateStorageForSession(reteEvaluator, "ep" + getEntryPointId()), + reteEvaluator.getSessionConfiguration().getPersistedSessionOption()) : new FullReliableObjectStore(StorageManagerFactory.get().getStorageManager().getOrCreateStorageForSession(reteEvaluator, "ep" + getEntryPointId())); } diff --git a/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SerializableStoredObject.java b/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SerializableStoredObject.java index 9495d5720a3..57a6c3c2702 100644 --- a/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SerializableStoredObject.java +++ b/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SerializableStoredObject.java @@ -19,7 +19,7 @@ public class SerializableStoredObject extends BaseStoredObject { - private final Serializable object; + protected final Serializable object; public SerializableStoredObject(Object object, boolean propagated) { super(propagated); diff --git a/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SerializableStoredRefObject.java b/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SerializableStoredRefObject.java new file mode 100644 index 00000000000..1313cd25be4 --- /dev/null +++ b/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SerializableStoredRefObject.java @@ -0,0 +1,39 @@ +package org.drools.reliability.core; + +import org.drools.core.common.Storage; + +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +public class SerializableStoredRefObject extends SerializableStoredObject { + + private final Map referencedObjects; + + public SerializableStoredRefObject(Object object, boolean propagated) { + super(object, propagated); + referencedObjects=new HashMap<>(); + } + + public void addReferencedObject(String fieldName, Long refObjectKey){ + this.referencedObjects.put(fieldName, refObjectKey); + } + + public StoredObject updateReferencedObjects(Storage storage){ + this.referencedObjects.keySet().forEach(fieldName -> { + Optional refField = Arrays.stream(object.getClass().getDeclaredFields()) + .filter(f -> f.getName().equals(fieldName)).findFirst(); + if (refField.isPresent()){ + refField.get().setAccessible(true); + try { + refField.get().set(this.object, storage.get(this.referencedObjects.get(refField.get().getName())).getObject()); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + }); + return this; + } +} diff --git a/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleReliableObjectStoreFactory.java b/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleReliableObjectStoreFactory.java index 3f195361382..188f90610c9 100644 --- a/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleReliableObjectStoreFactory.java +++ b/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleReliableObjectStoreFactory.java @@ -17,10 +17,11 @@ import org.drools.core.common.Storage; import org.kie.api.internal.utils.KieService; +import org.kie.api.runtime.conf.PersistedSessionOption; public interface SimpleReliableObjectStoreFactory extends KieService { - SimpleReliableObjectStore createSimpleReliableObjectStore(Storage storage); + SimpleReliableObjectStore createSimpleReliableObjectStore(Storage storage, PersistedSessionOption persistedSessionOption); class Holder { diff --git a/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableObjectStore.java b/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableObjectStore.java index 24acb1c5e6d..be5b99c5555 100644 --- a/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableObjectStore.java +++ b/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableObjectStore.java @@ -15,10 +15,6 @@ package org.drools.reliability.core; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; - import org.drools.core.ClockType; import org.drools.core.common.DefaultEventHandle; import org.drools.core.common.IdentityObjectStore; @@ -27,9 +23,13 @@ import org.drools.core.common.InternalWorkingMemoryEntryPoint; import org.drools.core.common.Storage; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + public class SimpleSerializationReliableObjectStore extends IdentityObjectStore implements SimpleReliableObjectStore { - protected final transient Storage storage; + protected transient Storage storage; protected boolean reInitPropagated = false; @@ -113,7 +113,7 @@ public void putIntoPersistedStorage(InternalFactHandle handle, boolean propagate storage.put(getHandleForObject(object).getId(), storedObject); } - private StoredObject factHandleToStoredObject(InternalFactHandle handle, boolean propagated, Object object) { + StoredObject factHandleToStoredObject(InternalFactHandle handle, boolean propagated, Object object) { return handle.isEvent() ? createStoredEvent(propagated, object, ((DefaultEventHandle) handle).getStartTimestamp(), ((DefaultEventHandle) handle).getDuration()) : createStoredObject(propagated, object); diff --git a/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableObjectStoreFactory.java b/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableObjectStoreFactory.java index 81478de918b..aad37b71998 100644 --- a/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableObjectStoreFactory.java +++ b/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableObjectStoreFactory.java @@ -16,6 +16,7 @@ package org.drools.reliability.core; import org.drools.core.common.Storage; +import org.kie.api.runtime.conf.PersistedSessionOption; public class SimpleSerializationReliableObjectStoreFactory implements SimpleReliableObjectStoreFactory { @@ -25,6 +26,14 @@ public SimpleReliableObjectStore createSimpleReliableObjectStore(Storage storage, PersistedSessionOption persistedSessionOption) { + if (persistedSessionOption.getPersistenceObjectsStrategy() == PersistedSessionOption.PersistenceObjectsStrategy.SIMPLE) { + return new SimpleSerializationReliableObjectStore(storage); + }else { + return new SimpleSerializationReliableRefObjectStore(storage); + } + } + @Override public int servicePriority() { return servicePriorityValue; diff --git a/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableRefObjectStore.java b/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableRefObjectStore.java new file mode 100644 index 00000000000..71279ad7420 --- /dev/null +++ b/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableRefObjectStore.java @@ -0,0 +1,86 @@ +package org.drools.reliability.core; + +import org.drools.core.common.InternalFactHandle; +import org.drools.core.common.Storage; + +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class SimpleSerializationReliableRefObjectStore extends SimpleSerializationReliableObjectStore { + + public SimpleSerializationReliableRefObjectStore(Storage storage) { + super(storage); + this.storage = storage.size()>0 ? updateObjectReferences(storage) : storage; + } + + private Storage updateObjectReferences(Storage storage){ + Storage updateStorage = storage; + + for (Long key: storage.keySet()){ + updateStorage.put(key, ((SerializableStoredRefObject) storage.get(key)).updateReferencedObjects(storage)); + } + return updateStorage; + } + + @Override + public void putIntoPersistedStorage(InternalFactHandle handle, boolean propagated) { + Object object = handle.getObject(); + StoredObject storedObject = factHandleToStoredObject(handle, reInitPropagated || propagated, object); + storage.put(getHandleForObject(object).getId(), setReferencedObjects(storedObject)); + } + + @Override + protected StoredObject createStoredObject(boolean propagated, Object object) { + return new SerializableStoredRefObject(object, propagated); + } + + private void updateReferencedObjects(StoredObject object){ + List referencedObjects = getReferencedObjects(object.getObject()); + if (referencedObjects.size()>0) { + + } + } + + private StoredObject setReferencedObjects(StoredObject object){ + List referencedObjects = getReferencedObjects(object.getObject()); + if (referencedObjects.size()>0) { + // for each referenced object in sObject + // lookup in storage, find the object of reference, get its fact handle id + // save this association in the StoredObject + referencedObjects.forEach(field -> { + field.setAccessible(true); + Object fieldObject = null; + try { + fieldObject = field.get(object.getObject()); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + Long objectKey = fromObjectToFactHandleId(fieldObject); + if (objectKey!=null){ + ((SerializableStoredRefObject) object).addReferencedObject(field.getName(), objectKey);} + }); + } + return object; + } + + private Long fromObjectToFactHandleId(Object object){ + for (Long key : this.storage.keySet()){ + if (( (SerializableStoredRefObject) storage.get(key)).getObject()==object){ + return key; + } + } + return null; + } + + private List getReferencedObjects(Object object){ + Field[] fields = object.getClass().getDeclaredFields(); + + List nonPrimitiveFields = Arrays.stream(fields) + .filter(field -> !field.getType().isPrimitive()) + .filter(field -> !field.getType().equals(String.class)) + .collect(Collectors.toList()); + return nonPrimitiveFields; + } +} diff --git a/drools-reliability/drools-reliability-infinispan/src/main/java/org/drools/reliability/infinispan/SimpleInfinispanReliableObjectStoreFactory.java b/drools-reliability/drools-reliability-infinispan/src/main/java/org/drools/reliability/infinispan/SimpleInfinispanReliableObjectStoreFactory.java index 5a28d66e6db..49ae4f3be96 100644 --- a/drools-reliability/drools-reliability-infinispan/src/main/java/org/drools/reliability/infinispan/SimpleInfinispanReliableObjectStoreFactory.java +++ b/drools-reliability/drools-reliability-infinispan/src/main/java/org/drools/reliability/infinispan/SimpleInfinispanReliableObjectStoreFactory.java @@ -19,9 +19,11 @@ import org.drools.reliability.core.SimpleReliableObjectStore; import org.drools.reliability.core.SimpleReliableObjectStoreFactory; import org.drools.reliability.core.SimpleSerializationReliableObjectStore; +import org.drools.reliability.core.SimpleSerializationReliableRefObjectStore; import org.drools.reliability.core.StorageManagerFactory; import org.drools.reliability.core.StoredObject; import org.drools.reliability.infinispan.proto.SimpleProtoStreamReliableObjectStore; +import org.kie.api.runtime.conf.PersistedSessionOption; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,13 +33,18 @@ public class SimpleInfinispanReliableObjectStoreFactory implements SimpleReliabl private static final Logger LOG = LoggerFactory.getLogger(SimpleInfinispanReliableObjectStoreFactory.class); - public SimpleReliableObjectStore createSimpleReliableObjectStore(Storage storage) { + public SimpleReliableObjectStore createSimpleReliableObjectStore(Storage storage, PersistedSessionOption persistedSessionOption) { if (((InfinispanStorageManager)StorageManagerFactory.get().getStorageManager()).isProtoStream()) { LOG.debug("Using SimpleProtoStreamReliableObjectStore"); return new SimpleProtoStreamReliableObjectStore(storage); } else { - LOG.debug("Using SimpleSerializationReliableObjectStore"); - return new SimpleSerializationReliableObjectStore(storage); + if (persistedSessionOption.getPersistenceObjectsStrategy()== PersistedSessionOption.PersistenceObjectsStrategy.OBJECT_REFERENCES){ + LOG.debug("Using SimpleSerializationReliableRefObjectStore"); + return new SimpleSerializationReliableRefObjectStore(storage); + }else{ + LOG.debug("Using SimpleSerializationReliableObjectStore"); + return new SimpleSerializationReliableObjectStore(storage); + } } } @@ -45,4 +52,5 @@ public SimpleReliableObjectStore createSimpleReliableObjectStore(Storage Date: Tue, 1 Aug 2023 09:58:16 +0300 Subject: [PATCH 2/7] Copyright header added --- .../core/SerializableStoredRefObject.java | 15 +++++++++++++++ ...SimpleSerializationReliableRefObjectStore.java | 15 +++++++++++++++ .../test/ReliabilityFireAndAlarmTest.java | 15 +++++++++++++++ .../java/org/test/domain/fireandalarm/Alarm.java | 15 +++++++++++++++ .../java/org/test/domain/fireandalarm/Fire.java | 15 +++++++++++++++ .../java/org/test/domain/fireandalarm/Room.java | 15 +++++++++++++++ .../org/test/domain/fireandalarm/Sprinkler.java | 15 +++++++++++++++ 7 files changed, 105 insertions(+) diff --git a/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SerializableStoredRefObject.java b/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SerializableStoredRefObject.java index 1313cd25be4..49e986a8226 100644 --- a/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SerializableStoredRefObject.java +++ b/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SerializableStoredRefObject.java @@ -1,3 +1,18 @@ +/* + * Copyright 2023 Red Hat, Inc. and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.drools.reliability.core; import org.drools.core.common.Storage; diff --git a/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableRefObjectStore.java b/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableRefObjectStore.java index 71279ad7420..f55d7c95aaa 100644 --- a/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableRefObjectStore.java +++ b/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableRefObjectStore.java @@ -1,3 +1,18 @@ +/* + * Copyright 2023 Red Hat, Inc. and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.drools.reliability.core; import org.drools.core.common.InternalFactHandle; diff --git a/drools-reliability/drools-reliability-tests/src/test/java/org/drools/reliability/test/ReliabilityFireAndAlarmTest.java b/drools-reliability/drools-reliability-tests/src/test/java/org/drools/reliability/test/ReliabilityFireAndAlarmTest.java index 83ea3bd6b6e..ae9d4c3a58a 100644 --- a/drools-reliability/drools-reliability-tests/src/test/java/org/drools/reliability/test/ReliabilityFireAndAlarmTest.java +++ b/drools-reliability/drools-reliability-tests/src/test/java/org/drools/reliability/test/ReliabilityFireAndAlarmTest.java @@ -1,3 +1,18 @@ +/* + * Copyright 2023 Red Hat, Inc. and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.drools.reliability.test; import org.junit.jupiter.params.ParameterizedTest; diff --git a/drools-reliability/drools-reliability-tests/src/test/java/org/test/domain/fireandalarm/Alarm.java b/drools-reliability/drools-reliability-tests/src/test/java/org/test/domain/fireandalarm/Alarm.java index e25215b97dc..70c3496c410 100644 --- a/drools-reliability/drools-reliability-tests/src/test/java/org/test/domain/fireandalarm/Alarm.java +++ b/drools-reliability/drools-reliability-tests/src/test/java/org/test/domain/fireandalarm/Alarm.java @@ -1,3 +1,18 @@ +/* + * Copyright 2023 Red Hat, Inc. and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.test.domain.fireandalarm; import java.io.Serializable; diff --git a/drools-reliability/drools-reliability-tests/src/test/java/org/test/domain/fireandalarm/Fire.java b/drools-reliability/drools-reliability-tests/src/test/java/org/test/domain/fireandalarm/Fire.java index 5e10af965e2..e4f44929c9a 100644 --- a/drools-reliability/drools-reliability-tests/src/test/java/org/test/domain/fireandalarm/Fire.java +++ b/drools-reliability/drools-reliability-tests/src/test/java/org/test/domain/fireandalarm/Fire.java @@ -1,3 +1,18 @@ +/* + * Copyright 2023 Red Hat, Inc. and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.test.domain.fireandalarm; import java.io.Serializable; diff --git a/drools-reliability/drools-reliability-tests/src/test/java/org/test/domain/fireandalarm/Room.java b/drools-reliability/drools-reliability-tests/src/test/java/org/test/domain/fireandalarm/Room.java index eda547988f5..cbb073779a6 100644 --- a/drools-reliability/drools-reliability-tests/src/test/java/org/test/domain/fireandalarm/Room.java +++ b/drools-reliability/drools-reliability-tests/src/test/java/org/test/domain/fireandalarm/Room.java @@ -1,3 +1,18 @@ +/* + * Copyright 2023 Red Hat, Inc. and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.test.domain.fireandalarm; import java.io.Serializable; diff --git a/drools-reliability/drools-reliability-tests/src/test/java/org/test/domain/fireandalarm/Sprinkler.java b/drools-reliability/drools-reliability-tests/src/test/java/org/test/domain/fireandalarm/Sprinkler.java index 610d7fd1882..67a085e2032 100644 --- a/drools-reliability/drools-reliability-tests/src/test/java/org/test/domain/fireandalarm/Sprinkler.java +++ b/drools-reliability/drools-reliability-tests/src/test/java/org/test/domain/fireandalarm/Sprinkler.java @@ -1,3 +1,18 @@ +/* + * Copyright 2023 Red Hat, Inc. and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.test.domain.fireandalarm; import java.io.Serializable; From 697143b24e83a38ae42cd5d0ddcd073adf455969 Mon Sep 17 00:00:00 2001 From: nprentza Date: Tue, 1 Aug 2023 14:07:27 +0300 Subject: [PATCH 3/7] addressing draft PR comments, improved test method --- ...impleSerializationReliableObjectStore.java | 2 +- ...leSerializationReliableRefObjectStore.java | 50 ++++++++++++++----- .../test/ReliabilityFireAndAlarmTest.java | 43 +++++++++++++++- .../test/ReliabilityTestBasics.java | 19 +++++++ 4 files changed, 100 insertions(+), 14 deletions(-) diff --git a/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableObjectStore.java b/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableObjectStore.java index be5b99c5555..71618647ee9 100644 --- a/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableObjectStore.java +++ b/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableObjectStore.java @@ -113,7 +113,7 @@ public void putIntoPersistedStorage(InternalFactHandle handle, boolean propagate storage.put(getHandleForObject(object).getId(), storedObject); } - StoredObject factHandleToStoredObject(InternalFactHandle handle, boolean propagated, Object object) { + protected StoredObject factHandleToStoredObject(InternalFactHandle handle, boolean propagated, Object object) { return handle.isEvent() ? createStoredEvent(propagated, object, ((DefaultEventHandle) handle).getStartTimestamp(), ((DefaultEventHandle) handle).getDuration()) : createStoredObject(propagated, object); diff --git a/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableRefObjectStore.java b/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableRefObjectStore.java index f55d7c95aaa..2fc9f3b36b1 100644 --- a/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableRefObjectStore.java +++ b/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableRefObjectStore.java @@ -20,13 +20,18 @@ import java.lang.reflect.Field; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; public class SimpleSerializationReliableRefObjectStore extends SimpleSerializationReliableObjectStore { + private Map uniqueObjectTypesInStore; + public SimpleSerializationReliableRefObjectStore(Storage storage) { super(storage); + uniqueObjectTypesInStore = new HashMap<>(); this.storage = storage.size()>0 ? updateObjectReferences(storage) : storage; } @@ -44,18 +49,20 @@ public void putIntoPersistedStorage(InternalFactHandle handle, boolean propagate Object object = handle.getObject(); StoredObject storedObject = factHandleToStoredObject(handle, reInitPropagated || propagated, object); storage.put(getHandleForObject(object).getId(), setReferencedObjects(storedObject)); + // also add the type of the object into the uniqueObjectTypesInStore list (if not already there) + this.putIntoObjectTypesList(object); } @Override - protected StoredObject createStoredObject(boolean propagated, Object object) { - return new SerializableStoredRefObject(object, propagated); + public void removeFromPersistedStorage(Object object) { + super.removeFromPersistedStorage(object); + // also remove instance from uniqueObjectTypesInStore + this.removeFromObjectTypesList(object); } - private void updateReferencedObjects(StoredObject object){ - List referencedObjects = getReferencedObjects(object.getObject()); - if (referencedObjects.size()>0) { - - } + @Override + protected StoredObject createStoredObject(boolean propagated, Object object) { + return new SerializableStoredRefObject(object, propagated); } private StoredObject setReferencedObjects(StoredObject object){ @@ -70,7 +77,7 @@ private StoredObject setReferencedObjects(StoredObject object){ try { fieldObject = field.get(object.getObject()); } catch (IllegalAccessException e) { - e.printStackTrace(); + throw new ReliabilityRuntimeException(e); } Long objectKey = fromObjectToFactHandleId(fieldObject); if (objectKey!=null){ @@ -92,10 +99,29 @@ private Long fromObjectToFactHandleId(Object object){ private List getReferencedObjects(Object object){ Field[] fields = object.getClass().getDeclaredFields(); - List nonPrimitiveFields = Arrays.stream(fields) - .filter(field -> !field.getType().isPrimitive()) - .filter(field -> !field.getType().equals(String.class)) + List fieldsWithTypeInTheStore = Arrays.stream(fields) + .filter(field -> uniqueObjectTypesInStore.keySet().contains(field.getType())) .collect(Collectors.toList()); - return nonPrimitiveFields; + return fieldsWithTypeInTheStore; + } + + private void putIntoObjectTypesList(Object object){ + Long objectTypeCount = uniqueObjectTypesInStore.get(object.getClass()); + if (objectTypeCount!=null){ + uniqueObjectTypesInStore.put(object.getClass(), objectTypeCount+1); + }else{ + uniqueObjectTypesInStore.put(object.getClass(),Integer.toUnsignedLong(1)); + } } + + private void removeFromObjectTypesList(Object object){ + Long objectTypeCount = uniqueObjectTypesInStore.get(object.getClass()); + if (objectTypeCount!=null){ + objectTypeCount--; + if (objectTypeCount==0){ + uniqueObjectTypesInStore.remove(object.getClass()); + }else {uniqueObjectTypesInStore.put(object.getClass(),objectTypeCount);} + } + } + } diff --git a/drools-reliability/drools-reliability-tests/src/test/java/org/drools/reliability/test/ReliabilityFireAndAlarmTest.java b/drools-reliability/drools-reliability-tests/src/test/java/org/drools/reliability/test/ReliabilityFireAndAlarmTest.java index ae9d4c3a58a..ad10f9ea8b5 100644 --- a/drools-reliability/drools-reliability-tests/src/test/java/org/drools/reliability/test/ReliabilityFireAndAlarmTest.java +++ b/drools-reliability/drools-reliability-tests/src/test/java/org/drools/reliability/test/ReliabilityFireAndAlarmTest.java @@ -24,6 +24,8 @@ import org.test.domain.fireandalarm.Room; import org.test.domain.fireandalarm.Sprinkler; +import java.util.Optional; + import static org.assertj.core.api.Assertions.assertThat; public class ReliabilityFireAndAlarmTest extends ReliabilityTestBasics{ @@ -90,13 +92,52 @@ void testInsertFailover_ShouldFireRules(PersistedSessionOption.PersistenceStrate createSession(FIRE_AND_ALARM, persistenceStrategy, safepointStrategy, PersistedSessionOption.PersistenceObjectsStrategy.OBJECT_REFERENCES); Room room1 = new Room("Room 1"); + Sprinkler sprinkler1 = new Sprinkler(room1); insert(room1); insert(new Fire(room1)); - insert(new Sprinkler(room1)); + insert(sprinkler1); failover(); restoreSession(FIRE_AND_ALARM, persistenceStrategy,safepointStrategy,PersistedSessionOption.PersistenceObjectsStrategy.OBJECT_REFERENCES); assertThat(fireAllRules()).isEqualTo(2); + Optional sprinklerR = getObjectByType(Sprinkler.class); + assertThat(sprinklerR.isEmpty()).isFalse(); + assertThat(((Sprinkler) sprinklerR.get()).isOn()).isTrue(); + } + + @ParameterizedTest + @MethodSource("strategyProviderStoresOnlyWithExplicitSafepoints") // does not support PersistedSessionOption.PersistenceObjectsStrategy.SIMPLE + void testPhase1FailoverPhase2Phase3_ShouldFireRules(PersistedSessionOption.PersistenceStrategy persistenceStrategy, PersistedSessionOption.SafepointStrategy safepointStrategy){ + createSession(FIRE_AND_ALARM, persistenceStrategy, safepointStrategy,PersistedSessionOption.PersistenceObjectsStrategy.OBJECT_REFERENCES); + + // phase 1 + Room room1 = new Room("Room 1"); + insert(room1); + insert(new Fire(room1)); + + assertThat(fireAllRules()).isEqualTo(1); + Optional alarm = getObjectByType(Alarm.class); + assertThat(alarm.isEmpty()).isFalse(); + + failover(); + restoreSession(FIRE_AND_ALARM, persistenceStrategy,safepointStrategy,PersistedSessionOption.PersistenceObjectsStrategy.OBJECT_REFERENCES); + + // phase 2 + Optional room = getObjectByType(Room.class); + assertThat(room.isEmpty()).isFalse(); + Sprinkler sprinkler1 = new Sprinkler((Room) room.get()); + insert(sprinkler1); + fireAllRules(); + + Optional sprinkler = getObjectByType(Sprinkler.class); + assertThat(sprinkler.isEmpty()).isFalse(); + assertThat(((Sprinkler) sprinkler.get()).isOn()).isTrue(); + + // phase 3 + Optional fireFh = getFactHandleByType(Fire.class); + assertThat(fireFh.isEmpty()).isFalse(); + delete(fireFh.get()); + assertThat(fireAllRules()).isEqualTo(1); } } diff --git a/drools-reliability/drools-reliability-tests/src/test/java/org/drools/reliability/test/ReliabilityTestBasics.java b/drools-reliability/drools-reliability-tests/src/test/java/org/drools/reliability/test/ReliabilityTestBasics.java index 37d3e5fe120..dc42fb7ad50 100644 --- a/drools-reliability/drools-reliability-tests/src/test/java/org/drools/reliability/test/ReliabilityTestBasics.java +++ b/drools-reliability/drools-reliability-tests/src/test/java/org/drools/reliability/test/ReliabilityTestBasics.java @@ -416,6 +416,25 @@ protected Optional getFactHandle(KieSession kieSession, Person perso .filter(p -> ( (Person) p.getObject()).getAge()==person.getAge() ).findFirst(); } + protected Optional getObjectByType(Class objectClass){ + return getObjectByType(sessions.get(0), objectClass); + } + + protected Optional getObjectByType(KieSession kieSession, Class objectClass){ + return (Optional) kieSession.getObjects(new ClassObjectFilter(objectClass)).stream().findFirst(); + } + + protected Optional getFactHandleByType(Class objectClass){ + return getFactHandleByType(sessions.get(0), objectClass); + } + + protected Optional getFactHandleByType(KieSession kieSession, Class objectClass){ + return kieSession.getFactHandles() + .stream() + .filter(fh -> fh.getObject().getClass().equals(objectClass)) + .findFirst(); + } + private static class OptionsFilter { private final Option[] options; From 42a8db3b9d99c0908d3a3b92c4010385347a0522 Mon Sep 17 00:00:00 2001 From: nprentza Date: Tue, 1 Aug 2023 15:56:35 +0300 Subject: [PATCH 4/7] add global results in testPhase1FailoverPhase2Phase3_ShouldFireRules --- .../test/ReliabilityFireAndAlarmTest.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drools-reliability/drools-reliability-tests/src/test/java/org/drools/reliability/test/ReliabilityFireAndAlarmTest.java b/drools-reliability/drools-reliability-tests/src/test/java/org/drools/reliability/test/ReliabilityFireAndAlarmTest.java index ad10f9ea8b5..a037043c638 100644 --- a/drools-reliability/drools-reliability-tests/src/test/java/org/drools/reliability/test/ReliabilityFireAndAlarmTest.java +++ b/drools-reliability/drools-reliability-tests/src/test/java/org/drools/reliability/test/ReliabilityFireAndAlarmTest.java @@ -40,13 +40,15 @@ public class ReliabilityFireAndAlarmTest extends ReliabilityTestBasics{ " $sprinkler: Sprinkler( room == $room, on == false ) \n" + "then\n" + " modify($sprinkler) { setOn(true); } \n" + - " System.out.println(\"Turn on the sprinkler for room\" + $room.getName()); \n" + + " System.out.println(\"Turn on the sprinkler for room \" + $room.getName()); \n" + + " results.add( \"Turn on sprinkler rule\" );\n" + "end\n" + "rule 'Raise the alarm when we have one or more firs' when\n" + " exists Fire() \n" + "then\n" + " insert( new Alarm() );\n" + " System.out.println(\"Raise the alarm\");\n" + + " results.add( \"Raise alarm rule\" );\n" + "end\n"+ "rule 'Cancel the alarm when all the fires have gone' when \n" + " not Fire() \n" + @@ -54,12 +56,14 @@ public class ReliabilityFireAndAlarmTest extends ReliabilityTestBasics{ "then\n" + " delete ( $alarm ); \n" + " System.out.println(\"Cancel the alarm\"); \n" + + " results.add( \"Cancel alarm rule\" );\n" + "end\n" + "rule 'Status output when things are ok' when\n" + " not Alarm() \n" + " not Sprinkler ( on == true ) \n" + "then \n" + " System.out.println(\"Everything is ok\"); \n" + + " results.add( \"Everything ok rule\" );\n" + "end"; @@ -117,18 +121,24 @@ void testPhase1FailoverPhase2Phase3_ShouldFireRules(PersistedSessionOption.Persi insert(new Fire(room1)); assertThat(fireAllRules()).isEqualTo(1); + assertThat(getResults()).containsExactlyInAnyOrder("Raise alarm rule"); + Optional alarm = getObjectByType(Alarm.class); assertThat(alarm.isEmpty()).isFalse(); failover(); restoreSession(FIRE_AND_ALARM, persistenceStrategy,safepointStrategy,PersistedSessionOption.PersistenceObjectsStrategy.OBJECT_REFERENCES); + clearResults(); // phase 2 Optional room = getObjectByType(Room.class); assertThat(room.isEmpty()).isFalse(); Sprinkler sprinkler1 = new Sprinkler((Room) room.get()); insert(sprinkler1); - fireAllRules(); + + assertThat(fireAllRules()).isEqualTo(1); + assertThat(getResults()).containsExactlyInAnyOrder("Turn on sprinkler rule"); + clearResults(); Optional sprinkler = getObjectByType(Sprinkler.class); assertThat(sprinkler.isEmpty()).isFalse(); @@ -139,5 +149,6 @@ void testPhase1FailoverPhase2Phase3_ShouldFireRules(PersistedSessionOption.Persi assertThat(fireFh.isEmpty()).isFalse(); delete(fireFh.get()); assertThat(fireAllRules()).isEqualTo(1); + assertThat(getResults()).containsExactlyInAnyOrder("Cancel alarm rule"); } } From 102c2ef9e845b1c76bfb292a8369b5c6ea491d39 Mon Sep 17 00:00:00 2001 From: nprentza Date: Wed, 2 Aug 2023 08:41:54 +0300 Subject: [PATCH 5/7] init uniqueObjectTypesInStore --- .../core/SimpleSerializationReliableRefObjectStore.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableRefObjectStore.java b/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableRefObjectStore.java index 2fc9f3b36b1..6ccf4d6e38b 100644 --- a/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableRefObjectStore.java +++ b/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableRefObjectStore.java @@ -32,6 +32,9 @@ public class SimpleSerializationReliableRefObjectStore extends SimpleSerializati public SimpleSerializationReliableRefObjectStore(Storage storage) { super(storage); uniqueObjectTypesInStore = new HashMap<>(); + if (storage.size()>0){ + storage.values().forEach(sObject -> {this.putIntoObjectTypesList( sObject.getObject() );}); + } this.storage = storage.size()>0 ? updateObjectReferences(storage) : storage; } @@ -100,7 +103,7 @@ private List getReferencedObjects(Object object){ Field[] fields = object.getClass().getDeclaredFields(); List fieldsWithTypeInTheStore = Arrays.stream(fields) - .filter(field -> uniqueObjectTypesInStore.keySet().contains(field.getType())) + .filter(field -> uniqueObjectTypesInStore.containsKey(field.getType())) .collect(Collectors.toList()); return fieldsWithTypeInTheStore; } From f278778d53994e2b130ae8aacb295e1130ccc8c0 Mon Sep 17 00:00:00 2001 From: nprentza Date: Fri, 4 Aug 2023 09:43:33 +0300 Subject: [PATCH 6/7] more tests, other improvements --- .../core/SerializableStoredRefObject.java | 2 +- ...leSerializationReliableRefObjectStore.java | 25 +++- .../test/ReliabilityFireAndAlarmTest.java | 138 ++++++++++++++++-- 3 files changed, 152 insertions(+), 13 deletions(-) diff --git a/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SerializableStoredRefObject.java b/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SerializableStoredRefObject.java index 49e986a8226..7093434a763 100644 --- a/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SerializableStoredRefObject.java +++ b/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SerializableStoredRefObject.java @@ -45,7 +45,7 @@ public StoredObject updateReferencedObjects(Storage storage) try { refField.get().set(this.object, storage.get(this.referencedObjects.get(refField.get().getName())).getObject()); } catch (IllegalAccessException e) { - e.printStackTrace(); + throw new ReliabilityRuntimeException(e); } } }); diff --git a/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableRefObjectStore.java b/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableRefObjectStore.java index 6ccf4d6e38b..ad5c36e4d21 100644 --- a/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableRefObjectStore.java +++ b/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableRefObjectStore.java @@ -19,6 +19,7 @@ import org.drools.core.common.Storage; import java.lang.reflect.Field; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -33,7 +34,7 @@ public SimpleSerializationReliableRefObjectStore(Storage sto super(storage); uniqueObjectTypesInStore = new HashMap<>(); if (storage.size()>0){ - storage.values().forEach(sObject -> {this.putIntoObjectTypesList( sObject.getObject() );}); + updateObjectTypesList(); } this.storage = storage.size()>0 ? updateObjectReferences(storage) : storage; } @@ -53,14 +54,14 @@ public void putIntoPersistedStorage(InternalFactHandle handle, boolean propagate StoredObject storedObject = factHandleToStoredObject(handle, reInitPropagated || propagated, object); storage.put(getHandleForObject(object).getId(), setReferencedObjects(storedObject)); // also add the type of the object into the uniqueObjectTypesInStore list (if not already there) - this.putIntoObjectTypesList(object); + this.updateObjectTypesList(object); } @Override public void removeFromPersistedStorage(Object object) { super.removeFromPersistedStorage(object); // also remove instance from uniqueObjectTypesInStore - this.removeFromObjectTypesList(object); + this.updateObjectTypesList(object); } @Override @@ -108,6 +109,24 @@ private List getReferencedObjects(Object object){ return fieldsWithTypeInTheStore; } + private void updateObjectTypesList(Object object){ + uniqueObjectTypesInStore.put(object.getClass(), + storage.values().stream().filter(sObject -> sObject.getObject().getClass().equals(object.getClass())).count()); + } + + private void updateObjectTypesList(){ + // list of unique object types in storage + List uTypes = new ArrayList<>(); + storage.values().forEach(sObject -> { + if (!uTypes.contains(sObject.getObject().getClass())){uTypes.add(sObject.getObject().getClass());} + }); + // add unique object types + their occurrences in uniqueObjectTypesInStore + uTypes.forEach(uType -> { + uniqueObjectTypesInStore.put(uType, + storage.values().stream().filter(sObject -> sObject.getObject().getClass().equals(uType)).count()); + }); + } + private void putIntoObjectTypesList(Object object){ Long objectTypeCount = uniqueObjectTypesInStore.get(object.getClass()); if (objectTypeCount!=null){ diff --git a/drools-reliability/drools-reliability-tests/src/test/java/org/drools/reliability/test/ReliabilityFireAndAlarmTest.java b/drools-reliability/drools-reliability-tests/src/test/java/org/drools/reliability/test/ReliabilityFireAndAlarmTest.java index a037043c638..3cbbb3660b6 100644 --- a/drools-reliability/drools-reliability-tests/src/test/java/org/drools/reliability/test/ReliabilityFireAndAlarmTest.java +++ b/drools-reliability/drools-reliability-tests/src/test/java/org/drools/reliability/test/ReliabilityFireAndAlarmTest.java @@ -28,7 +28,7 @@ import static org.assertj.core.api.Assertions.assertThat; -public class ReliabilityFireAndAlarmTest extends ReliabilityTestBasics{ +public class ReliabilityFireAndAlarmTest extends ReliabilityTestBasics { private static final String FIRE_AND_ALARM = "import " + Alarm.class.getCanonicalName() + ";" + "import " + Fire.class.getCanonicalName() + ";" + @@ -49,7 +49,7 @@ public class ReliabilityFireAndAlarmTest extends ReliabilityTestBasics{ " insert( new Alarm() );\n" + " System.out.println(\"Raise the alarm\");\n" + " results.add( \"Raise alarm rule\" );\n" + - "end\n"+ + "end\n" + "rule 'Cancel the alarm when all the fires have gone' when \n" + " not Fire() \n" + " $alarm : Alarm() \n" + @@ -69,7 +69,7 @@ public class ReliabilityFireAndAlarmTest extends ReliabilityTestBasics{ @ParameterizedTest @MethodSource("strategyProviderStoresOnlyWithExplicitSafepoints") - void testNoFailover(PersistedSessionOption.PersistenceStrategy persistenceStrategy, PersistedSessionOption.SafepointStrategy safepointStrategy){ + void testNoFailover(PersistedSessionOption.PersistenceStrategy persistenceStrategy, PersistedSessionOption.SafepointStrategy safepointStrategy) { createSession(FIRE_AND_ALARM, persistenceStrategy, safepointStrategy); // phase 1 @@ -91,8 +91,8 @@ void testNoFailover(PersistedSessionOption.PersistenceStrategy persistenceStrate } @ParameterizedTest - @MethodSource("strategyProviderStoresOnlyWithExplicitSafepoints") - void testInsertFailover_ShouldFireRules(PersistedSessionOption.PersistenceStrategy persistenceStrategy, PersistedSessionOption.SafepointStrategy safepointStrategy){ + @MethodSource("strategyProviderStoresOnlyWithExplicitSafepoints") // does not support PersistedSessionOption.PersistenceObjectsStrategy.SIMPLE + void testInsertFailover_ShouldFireRules(PersistedSessionOption.PersistenceStrategy persistenceStrategy, PersistedSessionOption.SafepointStrategy safepointStrategy) { createSession(FIRE_AND_ALARM, persistenceStrategy, safepointStrategy, PersistedSessionOption.PersistenceObjectsStrategy.OBJECT_REFERENCES); Room room1 = new Room("Room 1"); @@ -102,7 +102,7 @@ void testInsertFailover_ShouldFireRules(PersistedSessionOption.PersistenceStrate insert(sprinkler1); failover(); - restoreSession(FIRE_AND_ALARM, persistenceStrategy,safepointStrategy,PersistedSessionOption.PersistenceObjectsStrategy.OBJECT_REFERENCES); + restoreSession(FIRE_AND_ALARM, persistenceStrategy, safepointStrategy, PersistedSessionOption.PersistenceObjectsStrategy.OBJECT_REFERENCES); assertThat(fireAllRules()).isEqualTo(2); Optional sprinklerR = getObjectByType(Sprinkler.class); @@ -112,8 +112,8 @@ void testInsertFailover_ShouldFireRules(PersistedSessionOption.PersistenceStrate @ParameterizedTest @MethodSource("strategyProviderStoresOnlyWithExplicitSafepoints") // does not support PersistedSessionOption.PersistenceObjectsStrategy.SIMPLE - void testPhase1FailoverPhase2Phase3_ShouldFireRules(PersistedSessionOption.PersistenceStrategy persistenceStrategy, PersistedSessionOption.SafepointStrategy safepointStrategy){ - createSession(FIRE_AND_ALARM, persistenceStrategy, safepointStrategy,PersistedSessionOption.PersistenceObjectsStrategy.OBJECT_REFERENCES); + void testPhase1FailoverPhase2Phase3_ShouldFireRules(PersistedSessionOption.PersistenceStrategy persistenceStrategy, PersistedSessionOption.SafepointStrategy safepointStrategy) { + createSession(FIRE_AND_ALARM, persistenceStrategy, safepointStrategy, PersistedSessionOption.PersistenceObjectsStrategy.OBJECT_REFERENCES); // phase 1 Room room1 = new Room("Room 1"); @@ -127,9 +127,94 @@ void testPhase1FailoverPhase2Phase3_ShouldFireRules(PersistedSessionOption.Persi assertThat(alarm.isEmpty()).isFalse(); failover(); - restoreSession(FIRE_AND_ALARM, persistenceStrategy,safepointStrategy,PersistedSessionOption.PersistenceObjectsStrategy.OBJECT_REFERENCES); + restoreSession(FIRE_AND_ALARM, persistenceStrategy, safepointStrategy, PersistedSessionOption.PersistenceObjectsStrategy.OBJECT_REFERENCES); + clearResults(); + + // phase 2 + Optional room = getObjectByType(Room.class); + assertThat(room.isEmpty()).isFalse(); + Sprinkler sprinkler1 = new Sprinkler((Room) room.get()); + insert(sprinkler1); + + assertThat(fireAllRules()).isEqualTo(1); + assertThat(getResults()).containsExactlyInAnyOrder("Turn on sprinkler rule"); + clearResults(); + + Optional sprinkler = getObjectByType(Sprinkler.class); + assertThat(sprinkler.isEmpty()).isFalse(); + assertThat(((Sprinkler) sprinkler.get()).isOn()).isTrue(); + + // phase 3 + Optional fireFh = getFactHandleByType(Fire.class); + assertThat(fireFh.isEmpty()).isFalse(); + delete(fireFh.get()); + assertThat(fireAllRules()).isEqualTo(1); + assertThat(getResults()).containsExactlyInAnyOrder("Cancel alarm rule"); + } + + @ParameterizedTest + @MethodSource("strategyProviderStoresOnlyWithExplicitSafepoints") // does not support PersistedSessionOption.PersistenceObjectsStrategy.SIMPLE + void testPhase1FailoverPhase2FailoverPhase3_ShouldFireRules(PersistedSessionOption.PersistenceStrategy persistenceStrategy, PersistedSessionOption.SafepointStrategy safepointStrategy) { + createSession(FIRE_AND_ALARM, persistenceStrategy, safepointStrategy, PersistedSessionOption.PersistenceObjectsStrategy.OBJECT_REFERENCES); + + // phase 1 + Room room1 = new Room("Room 1"); + insert(room1); + insert(new Fire(room1)); + + assertThat(fireAllRules()).isEqualTo(1); + assertThat(getResults()).containsExactlyInAnyOrder("Raise alarm rule"); + + Optional alarm = getObjectByType(Alarm.class); + assertThat(alarm.isEmpty()).isFalse(); + + failover(); + restoreSession(FIRE_AND_ALARM, persistenceStrategy, safepointStrategy, PersistedSessionOption.PersistenceObjectsStrategy.OBJECT_REFERENCES); + clearResults(); + + // phase 2 + Optional room = getObjectByType(Room.class); + assertThat(room.isEmpty()).isFalse(); + Sprinkler sprinkler1 = new Sprinkler((Room) room.get()); + insert(sprinkler1); + + assertThat(fireAllRules()).isEqualTo(1); + assertThat(getResults()).containsExactlyInAnyOrder("Turn on sprinkler rule"); + clearResults(); + + Optional sprinkler = getObjectByType(Sprinkler.class); + assertThat(sprinkler.isEmpty()).isFalse(); + assertThat(((Sprinkler) sprinkler.get()).isOn()).isTrue(); + + failover(); + restoreSession(FIRE_AND_ALARM, persistenceStrategy, safepointStrategy, PersistedSessionOption.PersistenceObjectsStrategy.OBJECT_REFERENCES); + clearResults(); + + // phase 3 + Optional fireFh = getFactHandleByType(Fire.class); + assertThat(fireFh.isEmpty()).isFalse(); + delete(fireFh.get()); + assertThat(fireAllRules()).isEqualTo(1); + assertThat(getResults()).containsExactlyInAnyOrder("Cancel alarm rule"); + } + + @ParameterizedTest + @MethodSource("strategyProviderStoresOnlyWithExplicitSafepoints") // does not support PersistedSessionOption.PersistenceObjectsStrategy.SIMPLE + void testPhase1Phase2FailoverPhase3_ShouldFireRules(PersistedSessionOption.PersistenceStrategy persistenceStrategy, PersistedSessionOption.SafepointStrategy safepointStrategy) { + createSession(FIRE_AND_ALARM, persistenceStrategy, safepointStrategy, PersistedSessionOption.PersistenceObjectsStrategy.OBJECT_REFERENCES); + + // phase 1 + Room room1 = new Room("Room 1"); + insert(room1); + insert(new Fire(room1)); + + assertThat(fireAllRules()).isEqualTo(1); + assertThat(getResults()).containsExactlyInAnyOrder("Raise alarm rule"); clearResults(); + Optional alarm = getObjectByType(Alarm.class); + assertThat(alarm.isEmpty()).isFalse(); + // phase 2 Optional room = getObjectByType(Room.class); assertThat(room.isEmpty()).isFalse(); @@ -144,6 +229,10 @@ void testPhase1FailoverPhase2Phase3_ShouldFireRules(PersistedSessionOption.Persi assertThat(sprinkler.isEmpty()).isFalse(); assertThat(((Sprinkler) sprinkler.get()).isOn()).isTrue(); + failover(); + restoreSession(FIRE_AND_ALARM, persistenceStrategy, safepointStrategy, PersistedSessionOption.PersistenceObjectsStrategy.OBJECT_REFERENCES); + clearResults(); + // phase 3 Optional fireFh = getFactHandleByType(Fire.class); assertThat(fireFh.isEmpty()).isFalse(); @@ -151,4 +240,35 @@ void testPhase1FailoverPhase2Phase3_ShouldFireRules(PersistedSessionOption.Persi assertThat(fireAllRules()).isEqualTo(1); assertThat(getResults()).containsExactlyInAnyOrder("Cancel alarm rule"); } + + @ParameterizedTest + @MethodSource("strategyProviderStoresOnlyWithExplicitSafepoints") // does not support PersistedSessionOption.PersistenceObjectsStrategy.SIMPLE + void testInsertFailoverUpdate_shouldFireRules(PersistedSessionOption.PersistenceStrategy persistenceStrategy, PersistedSessionOption.SafepointStrategy safepointStrategy) { + createSession(FIRE_AND_ALARM, persistenceStrategy, safepointStrategy, PersistedSessionOption.PersistenceObjectsStrategy.OBJECT_REFERENCES); + + Room room1 = new Room("Room 1"); + insert(room1); + Sprinkler sprinkler1 = new Sprinkler(room1); + insert(sprinkler1); + insert(new Fire(room1)); + + assertThat(fireAllRules()).isEqualTo(2); + assertThat(getResults()).containsExactlyInAnyOrder("Turn on sprinkler rule", "Raise alarm rule"); + + failover(); + restoreSession(FIRE_AND_ALARM, persistenceStrategy, safepointStrategy, PersistedSessionOption.PersistenceObjectsStrategy.OBJECT_REFERENCES); + clearResults(); + + Optional fireFh = this.getFactHandleByType(Fire.class); + delete(fireFh.get()); + + Optional sprinklerFh = this.getFactHandleByType(Sprinkler.class); + Sprinkler sprinkler2 = ((Sprinkler) sprinklerFh.get().getObject()); + sprinkler2.setOn(false); + update(sprinklerFh.get(), sprinkler2); + + assertThat(fireAllRules()).isEqualTo(2); + assertThat(getResults()).containsExactlyInAnyOrder("Everything ok rule", "Cancel alarm rule"); + + } } From 6b9415872d771ac640b5d5506375b9281230faeb Mon Sep 17 00:00:00 2001 From: nprentza Date: Fri, 4 Aug 2023 15:34:03 +0300 Subject: [PATCH 7/7] sonar improvements --- ...leSerializationReliableRefObjectStore.java | 77 ++++++++----------- 1 file changed, 34 insertions(+), 43 deletions(-) diff --git a/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableRefObjectStore.java b/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableRefObjectStore.java index ad5c36e4d21..11366f34e9f 100644 --- a/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableRefObjectStore.java +++ b/drools-reliability/drools-reliability-core/src/main/java/org/drools/reliability/core/SimpleSerializationReliableRefObjectStore.java @@ -28,21 +28,25 @@ public class SimpleSerializationReliableRefObjectStore extends SimpleSerializationReliableObjectStore { - private Map uniqueObjectTypesInStore; + private Map uniqueObjectTypesInStore; // object type name, occurances + + public SimpleSerializationReliableRefObjectStore() { + throw new UnsupportedOperationException("This constructor should never be called"); + } public SimpleSerializationReliableRefObjectStore(Storage storage) { super(storage); uniqueObjectTypesInStore = new HashMap<>(); - if (storage.size()>0){ + if (storage.size() > 0) { updateObjectTypesList(); } - this.storage = storage.size()>0 ? updateObjectReferences(storage) : storage; + this.storage = storage.size() > 0 ? updateObjectReferences(storage) : storage; } - private Storage updateObjectReferences(Storage storage){ + private Storage updateObjectReferences(Storage storage) { Storage updateStorage = storage; - for (Long key: storage.keySet()){ + for (Long key : storage.keySet()) { updateStorage.put(key, ((SerializableStoredRefObject) storage.get(key)).updateReferencedObjects(storage)); } return updateStorage; @@ -69,9 +73,9 @@ protected StoredObject createStoredObject(boolean propagated, Object object) { return new SerializableStoredRefObject(object, propagated); } - private StoredObject setReferencedObjects(StoredObject object){ + private StoredObject setReferencedObjects(StoredObject object) { List referencedObjects = getReferencedObjects(object.getObject()); - if (referencedObjects.size()>0) { + if (!referencedObjects.isEmpty()) { // for each referenced object in sObject // lookup in storage, find the object of reference, get its fact handle id // save this association in the StoredObject @@ -84,66 +88,53 @@ private StoredObject setReferencedObjects(StoredObject object){ throw new ReliabilityRuntimeException(e); } Long objectKey = fromObjectToFactHandleId(fieldObject); - if (objectKey!=null){ - ((SerializableStoredRefObject) object).addReferencedObject(field.getName(), objectKey);} + if (objectKey != null) { + ((SerializableStoredRefObject) object).addReferencedObject(field.getName(), objectKey); + } }); } return object; } - private Long fromObjectToFactHandleId(Object object){ - for (Long key : this.storage.keySet()){ - if (( (SerializableStoredRefObject) storage.get(key)).getObject()==object){ + private Long fromObjectToFactHandleId(Object object) { + for (Long key : this.storage.keySet()) { + if (((SerializableStoredRefObject) storage.get(key)).getObject() == object) { return key; } } return null; } - private List getReferencedObjects(Object object){ + private List getReferencedObjects(Object object) { Field[] fields = object.getClass().getDeclaredFields(); - List fieldsWithTypeInTheStore = Arrays.stream(fields) - .filter(field -> uniqueObjectTypesInStore.containsKey(field.getType())) + return Arrays.stream(fields) + .filter(field -> uniqueObjectTypesInStore.containsKey(field.getType().getName())) .collect(Collectors.toList()); - return fieldsWithTypeInTheStore; } - private void updateObjectTypesList(Object object){ - uniqueObjectTypesInStore.put(object.getClass(), + private void updateObjectTypesList(Object object) { + uniqueObjectTypesInStore.put(object.getClass().getName(), storage.values().stream().filter(sObject -> sObject.getObject().getClass().equals(object.getClass())).count()); + // if count==0 then remove entry + if (uniqueObjectTypesInStore.get(object.getClass().getName()) == 0) { + uniqueObjectTypesInStore.remove(object.getClass().getName()); + } } - private void updateObjectTypesList(){ + private void updateObjectTypesList() { // list of unique object types in storage - List uTypes = new ArrayList<>(); + List uTypeNames = new ArrayList<>(); storage.values().forEach(sObject -> { - if (!uTypes.contains(sObject.getObject().getClass())){uTypes.add(sObject.getObject().getClass());} + if (!uTypeNames.contains(sObject.getObject().getClass().getName())) { + uTypeNames.add(sObject.getObject().getClass().getName()); + } }); // add unique object types + their occurrences in uniqueObjectTypesInStore - uTypes.forEach(uType -> { + uTypeNames.forEach(uType -> { uniqueObjectTypesInStore.put(uType, - storage.values().stream().filter(sObject -> sObject.getObject().getClass().equals(uType)).count()); + storage.values().stream().filter(sObject -> sObject.getObject().getClass().getName().equals(uType)).count()); }); } - - private void putIntoObjectTypesList(Object object){ - Long objectTypeCount = uniqueObjectTypesInStore.get(object.getClass()); - if (objectTypeCount!=null){ - uniqueObjectTypesInStore.put(object.getClass(), objectTypeCount+1); - }else{ - uniqueObjectTypesInStore.put(object.getClass(),Integer.toUnsignedLong(1)); - } - } - - private void removeFromObjectTypesList(Object object){ - Long objectTypeCount = uniqueObjectTypesInStore.get(object.getClass()); - if (objectTypeCount!=null){ - objectTypeCount--; - if (objectTypeCount==0){ - uniqueObjectTypesInStore.remove(object.getClass()); - }else {uniqueObjectTypesInStore.put(object.getClass(),objectTypeCount);} - } - } - } +