Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Entry listener with predicate should be notified on value entry/exit from predicate value space #8340

Merged
merged 3 commits into from Jul 7, 2016

Conversation

vbekiaris
Copy link
Collaborator

This PR introduces filtering strategies in map event publisher, to facilitate building a 'query cache' style listener with predicate on IMap . Default filtering strategy maintains Hazelcast entry events behavior. A new filtering strategy has been introduced which processes UPDATED entry events and, depending on listener's predicate, may alter the type of event, to match exit/entry of value from predicate value space.

An EE counterpart is required.

@vbekiaris vbekiaris added this to the 3.7 milestone Jun 7, 2016
@vbekiaris vbekiaris self-assigned this Jun 7, 2016
@devOpsHazelcast
Copy link
Collaborator

Test PASSed.

@devOpsHazelcast
Copy link
Collaborator

Test FAILed.

@vbekiaris vbekiaris changed the title [DONT MERGE] Entry listener with predicate should be notified on value entry/exit from predicate value space Entry listener with predicate should be notified on value entry/exit from predicate value space Jun 8, 2016
@devOpsHazelcast
Copy link
Collaborator

Test FAILed.

@vbekiaris
Copy link
Collaborator Author

IssuesTest::testIssue321_3 fails due to expectation that an entry event which include values will be published before the same event is published to another listener who excludes values. Since there are no event delivery order guarantees, changing the test to verify one event with value and another event without value are received by the listener, in any order.

@devOpsHazelcast
Copy link
Collaborator

Test PASSed.

Object mergingValue) {

Map<Integer, EntryEventData> eventDataIncludingValues = new Int2ObjectHashMap<EntryEventData>(EVENT_DATA_MAP_CAPACITY);
Map<Integer, EntryEventData> eventDataExcludingValues = new Int2ObjectHashMap<EntryEventData>(EVENT_DATA_MAP_CAPACITY);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can defer Int2ObjectHashMap creation at a later point, and can do it when needed, now for ex., if i have value-included event registrations and don't have any value-excluded ones, there will be always two Int2ObjectHashMap instance creation although one is sufficient. This event publishing part is on hot-path and it is better to create possible minimum number of objects.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, deferred map creation until actually needed.

@devOpsHazelcast
Copy link
Collaborator

Test FAILed.

@devOpsHazelcast
Copy link
Collaborator

Test PASSed.

Object mergingValue) {

Map<Integer, EntryEventData> eventDataIncludingValues = null;
Map<Integer, EntryEventData> eventDataExcludingValues = null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't an ArrayList cheaper than Map to hold event data in terms of number of created objects and calculations needed for hash? Seems an ArrayList is a better fit here and no need a Map

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The need here is to maintain a mapping from event type of event-to-be-published to the EntryEventData object (which can be reused across events published to listeners). At the moment, given the filtering strategies implemented in this PR, in the worst case for an UPDATED event we might create 2 more entries for event types REMOVED and ADDED (when the QueryCacheNaturalFilteringStrategy is used and appropriately configured listeners with predicates are registered).
On the other hand, with the default filtering strategy, there is no need to use a map at all, we just need to maintain two possible forms of the EntryEventData (with & without values), so in this case the Maps are indeed overkill.
Caching EntryEventData is not a direct concern of the chosen filtering strategy, however the caching implementation can be optimized depending on the chosen filtering strategy, so I will try something like introducing a new interface EntryEventDataCache, with an instance obtainable from the FilteringStrategy itself:

interface EntryEventDataCache {
  EntryEventData getOrCreateEventData(mapName, caller, dataKey, value, oldValue, mergingValue, eventTypeForPublishing);
}

interface FilteringStrategy {
....
   EntryEventDataCache getEntryEventDataCache();
}

@devOpsHazelcast
Copy link
Collaborator

Test FAILed.

@devOpsHazelcast
Copy link
Collaborator

Test FAILed.

@vbekiaris vbekiaris force-pushed the master-event-predicate branch 2 times, most recently from d58c92b to 49c8653 Compare June 22, 2016 11:11
@devOpsHazelcast
Copy link
Collaborator

Test PASSed.

1 similar comment
@devOpsHazelcast
Copy link
Collaborator

Test PASSed.

@ahmetmircik
Copy link
Member

Maybe you want to remove some unused methods in MapEventPublisherImpl, stumbled them when i get your branch my local,

other than that LGTM 👍

@vbekiaris
Copy link
Collaborator Author

Good catch, thanks for pointing that out.

@devOpsHazelcast
Copy link
Collaborator

Test FAILed.

@vbekiaris
Copy link
Collaborator Author

The MapEventPublisherImplTest committed previously erroneously tests that EntryEvent objects received by listeners are the same, however this is not the case: even though a single EntryEventData object is used to dispatch the event to listeners, ultimately a new DataAwareEntryEvent object is delivered to each listener. Working on replacing this test with another one that actually tests the operation of each EntryEventDataCache implementation.

@devOpsHazelcast
Copy link
Collaborator

Test PASSed.

@vbekiaris
Copy link
Collaborator Author

run-lab-run

@devOpsHazelcast
Copy link
Collaborator

Test PASSed.

@Override
public int doFilter(EventFilter filter, Data dataKey, Object dataOldValue, Object dataValue, EntryEventType eventType,
String mapNameOrNull) {
if (filter instanceof MapPartitionLostEventFilter) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why can the mapName be null?

@tombujok
Copy link
Contributor

👍 good job (some minor comments)

@vbekiaris
Copy link
Collaborator Author

Thanks @ahmetmircik & @tombujok, I pushed updated javadoc & fixed the argument name that was leftover as mapNameOrNull. When green, will squash & commit.

@devOpsHazelcast
Copy link
Collaborator

Test PASSed.

private Extractors getExtractorsForMapName(String mapName) {
if (mapName == null) {
return Extractors.empty();
}
Copy link
Contributor

@tombujok tombujok Jun 29, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aha, one more thing. If the mapName can't be null (since you changed it in the last commit) is this null check here necessary?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This null check was introduced in faa6428 but I don't think there are any chances mapName could be null as all code paths arrive at this point via one of publishEvent variants and the callers are various map operations, which should have a non-null map name.

@devOpsHazelcast
Copy link
Collaborator

Test FAILed.

…ring strategy maintains Hazelcast entry events behavior. New filtering strategy introduced which processes UPDATED entry events and, depending on listener's predicate, may alter the type event, to match exit/entry of value from predicate value space.
@vbekiaris
Copy link
Collaborator Author

Unrelated test failure com.hazelcast.durableexecutor.DurableExecutorServiceTest.testStatsIssue2039:

java.util.concurrent.ExecutionException: java.util.concurrent.RejectedExecutionException: Capacity[1] is reached!!! 
    at com.hazelcast.durableexecutor.impl.TaskRingBuffer.findEmptySpot(TaskRingBuffer.java:70)
    at com.hazelcast.durableexecutor.impl.TaskRingBuffer.add(TaskRingBuffer.java:60)
    at com.hazelcast.durableexecutor.impl.DurableExecutorContainer.execute(DurableExecutorContainer.java:59)
    at com.hazelcast.durableexecutor.impl.operations.TaskOperation.run(TaskOperation.java:47)
    at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.run(OperationRunnerImpl.java:182)
    at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.process(OperationThread.java:122)
    at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.run(OperationThread.java:102)
    at ------ submitted from ------.(Unknown Source)
    at com.hazelcast.spi.impl.operationservice.impl.InvocationFuture.resolve(InvocationFuture.java:111)
    at com.hazelcast.spi.impl.operationservice.impl.InvocationFuture.resolveAndThrow(InvocationFuture.java:74)
    at com.hazelcast.spi.impl.AbstractInvocationFuture.get(AbstractInvocationFuture.java:158)
    at com.hazelcast.durableexecutor.impl.DurableExecutorServiceProxy.submitToPartition(DurableExecutorServiceProxy.java:243)
    at com.hazelcast.durableexecutor.impl.DurableExecutorServiceProxy.submit(DurableExecutorServiceProxy.java:131)
    at com.hazelcast.durableexecutor.DurableExecutorServiceTest.testStatsIssue2039(DurableExecutorServiceTest.java:452)

@vbekiaris
Copy link
Collaborator Author

run-lab-run

@devOpsHazelcast
Copy link
Collaborator

Test PASSed.

@devOpsHazelcast
Copy link
Collaborator

Test PASSed.

@devOpsHazelcast
Copy link
Collaborator

Test PASSed.

@vbekiaris vbekiaris merged commit c57d334 into hazelcast:master Jul 7, 2016
@vbekiaris vbekiaris deleted the master-event-predicate branch July 7, 2016 12:12
@mmedenjak mmedenjak added the Source: Internal PR or issue was opened by an employee label Apr 13, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Source: Internal PR or issue was opened by an employee Team: Core Type: Defect
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants