Skip to content

Hazelcast4SessionUpdateEntryProcessor does not keep existing TTL of session map entry #1899

Closed
@AndreasKasparek

Description

@AndreasKasparek

Describe the bug
Hazelcast 4 has changed the way time-to-live on IMap entries are handled with hazelcast/hazelcast#10965. A set/put without a given TTL will reset the TTL of the entry to the value configured on the map or max value (it will not keep the existing TTL of the entry as Hazelcast 3 has done). That also applies to operations done on a MapEntry from within an EntryProcessor.

The Hazelcast4SessionUpdateEntryProcessor uses similar same logic as the old one for Hazelcast 3: it only specifies a TTL when updating the entry in the Hazelcast map if the TTL value of the session was actually changed.

if (this.maxInactiveInterval != null) {
((ExtendedMapEntry)entry).setValue(value, this.maxInactiveInterval.getSeconds(), TimeUnit.SECONDS);
} else {
entry.setValue(value);
}

The field this.maxInactiveInterval on the EntryProcessor is only set if someone changed the TTL of an existing Session (via HazelcastSession.setMaxInactiveInterval(Duration interval)). If that value was not changed, this field will be null and therefore entry.setValue(value) will be called. Which will reset any previously set TTL on this MapEntry back to the map config/max value, effectively removing any session timeout configured via Spring properties.

To Reproduce
Create a Hazelcast4IndexedSessionRepositry and set the defaultMaxInactiveInterval on it to e.g. 60 seconds. Create a new session and save it. This session now correctly has a TTL of 60 seconds in Hazelcast's IMap.

Now change anything on this session (e.g. add a new attribute) except for its maxInactiveInterval. On Hazelcast4IndexedSessionRepository.save() a new Hazelcast4SessionUpdateEntryProcessor will be created but its maxInactiveInterval will be null because session.maxInactiveIntervalChanged is false. This leads to the above behavior. If you check the EntryView of the session in the IMap after the EntryProcessor was executed you will see that the TTL is now set to max value (not 60 seconds anymore).

Note: the HazelcastSession object is still expired by the code checks in Hazelcast4IndexedSessionRepositry.findById() because the maxInactiveInterval value stored within the session object is not cleared, of course. But Hazelcast itself will not expire the map entry anymore in the expected amount of time. So if there is no further read access to this session after its timeout interval has passed, it will never get evicted and therefore no expiration event will be fired by Hazelcast. That breaks all listeners that depend on these events (e.g. auditing).

Expected behavior
Given the new behavior of Hazelcast 4, I would expect that the Hazelcast4SessionUpdateEntryProcessor always calls ((ExtendedMapEntry)entry).setValue(value, ttl.getSeconds(), TimeUnit.SECONDS); to update the map entry if Hazelcast4IndexedSessionRepositry .defaultMaxInactiveInterval is not null.

It should use this.maxInactiveInterval as ttl if there was a change to this value, otherwise it should use the previous value from session.getMaxInactiveInterval() as ttl instead.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions