Skip to content

Commit 931e077

Browse files
authored
Implement map.ttl (#216)
1 parent 0a9a2dc commit 931e077

File tree

4 files changed

+85
-12
lines changed

4 files changed

+85
-12
lines changed

hazelcast/protocol/codec/map_message_type.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,4 @@
5555
MAP_VALUESWITHPAGINGPREDICATE = 0x0139
5656
MAP_ENTRIESWITHPAGINGPREDICATE = 0x013a
5757
MAP_CLEARNEARCACHE = 0x013b
58+
MAP_SETTTL = 0x0149
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
from hazelcast.serialization.bits import *
2+
from hazelcast.protocol.client_message import ClientMessage
3+
from hazelcast.protocol.custom_codec import *
4+
from hazelcast.util import ImmutableLazyDataList
5+
from hazelcast.protocol.codec.map_message_type import *
6+
7+
REQUEST_TYPE = MAP_SETTTL
8+
RESPONSE_TYPE = 101
9+
RETRYABLE = False
10+
11+
12+
def calculate_size(name, key, ttl):
13+
""" Calculates the request payload size"""
14+
data_size = 0
15+
data_size += calculate_size_str(name)
16+
data_size += calculate_size_data(key)
17+
data_size += LONG_SIZE_IN_BYTES
18+
return data_size
19+
20+
21+
def encode_request(name, key, ttl):
22+
""" Encode request into client_message"""
23+
client_message = ClientMessage(payload_size=calculate_size(name, key, ttl))
24+
client_message.set_message_type(REQUEST_TYPE)
25+
client_message.set_retryable(RETRYABLE)
26+
client_message.append_str(name)
27+
client_message.append_data(key)
28+
client_message.append_long(ttl)
29+
client_message.update_frame_length()
30+
return client_message
31+
32+
33+
def decode_response(client_message, to_object=None):
34+
""" Decode response from client message"""
35+
parameters = dict(response=None)
36+
parameters['response'] = client_message.read_bool()
37+
return parameters
38+
39+
40+

hazelcast/proxy/map.py

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,19 @@
33
from hazelcast.future import combine_futures, ImmediateFuture
44
from hazelcast.near_cache import NearCache
55
from hazelcast.protocol.codec import map_add_entry_listener_codec, map_add_entry_listener_to_key_codec, \
6-
map_add_entry_listener_with_predicate_codec, map_add_entry_listener_to_key_with_predicate_codec, \
7-
map_add_index_codec, map_clear_codec, map_contains_key_codec, map_contains_value_codec, map_delete_codec, \
8-
map_entry_set_codec, map_entries_with_predicate_codec, map_evict_codec, map_evict_all_codec, map_flush_codec, \
9-
map_force_unlock_codec, map_get_codec, map_get_all_codec, map_get_entry_view_codec, map_is_empty_codec, \
10-
map_is_locked_codec, map_key_set_codec, map_key_set_with_predicate_codec, map_load_all_codec, \
11-
map_load_given_keys_codec, map_lock_codec, map_put_codec, map_put_all_codec, map_put_if_absent_codec, \
12-
map_put_transient_codec, map_size_codec, map_remove_codec, map_remove_if_same_codec, \
13-
map_remove_entry_listener_codec, map_replace_codec, map_replace_if_same_codec, map_set_codec, map_try_lock_codec, \
14-
map_try_put_codec, map_try_remove_codec, map_unlock_codec, map_values_codec, map_values_with_predicate_codec, \
15-
map_add_interceptor_codec, map_execute_on_all_keys_codec, map_execute_on_key_codec, map_execute_on_keys_codec, \
16-
map_execute_with_predicate_codec, map_add_near_cache_entry_listener_codec, map_entries_with_paging_predicate_codec,\
17-
map_key_set_with_paging_predicate_codec, map_values_with_paging_predicate_codec
6+
map_add_entry_listener_to_key_with_predicate_codec, map_add_entry_listener_with_predicate_codec, \
7+
map_add_index_codec, map_add_interceptor_codec, map_add_near_cache_entry_listener_codec, \
8+
map_clear_codec, map_contains_key_codec, map_contains_value_codec, map_delete_codec, \
9+
map_entries_with_paging_predicate_codec, map_entries_with_predicate_codec, map_entry_set_codec, \
10+
map_evict_all_codec, map_evict_codec, map_execute_on_all_keys_codec, map_execute_on_key_codec, \
11+
map_execute_on_keys_codec, map_execute_with_predicate_codec, map_flush_codec, map_force_unlock_codec, \
12+
map_get_all_codec, map_get_codec, map_get_entry_view_codec, map_is_empty_codec, map_is_locked_codec, \
13+
map_key_set_codec, map_key_set_with_paging_predicate_codec, map_key_set_with_predicate_codec, \
14+
map_load_all_codec, map_load_given_keys_codec, map_lock_codec, map_put_all_codec, map_put_codec, \
15+
map_put_if_absent_codec, map_put_transient_codec, map_remove_codec, map_remove_entry_listener_codec, \
16+
map_remove_if_same_codec, map_replace_codec, map_replace_if_same_codec, map_set_codec, \
17+
map_set_ttl_codec, map_size_codec, map_try_lock_codec, map_try_put_codec, map_try_remove_codec, \
18+
map_unlock_codec, map_values_codec, map_values_with_paging_predicate_codec, map_values_with_predicate_codec
1819
from hazelcast.proxy.base import Proxy, EntryEvent, EntryEventType, get_entry_listener_flags, MAX_SIZE
1920
from hazelcast.util import check_not_none, thread_id, to_millis, get_sorted_query_result_set, ITERATION_TYPE
2021
from hazelcast import six
@@ -740,6 +741,21 @@ def set(self, key, value, ttl=-1):
740741
value_data = self._to_data(value)
741742
return self._set_internal(key_data, value_data, ttl)
742743

744+
def set_ttl(self, key, ttl):
745+
"""
746+
Updates the TTL (time to live) value of the entry specified by the given key with a new TTL value. New TTL
747+
value is valid starting from the time this operation is invoked, not since the time the entry was created.
748+
If the entry does not exist or is already expired, this call has no effect.
749+
750+
:param key: (object), the key of the map entry.
751+
:param ttl: (int), maximum time for this entry to stay in the map (0 means infinite,
752+
negative means map config default)
753+
"""
754+
check_not_none(key, "key can't be None")
755+
check_not_none(ttl, "ttl can't be None")
756+
key_data = self._to_data(key)
757+
return self._set_ttl_internal(key_data, ttl)
758+
743759
def size(self):
744760
"""
745761
Returns the number of entries in this map.
@@ -882,6 +898,9 @@ def _set_internal(self, key_data, value_data, ttl):
882898
return self._encode_invoke_on_key(map_set_codec, key_data, key=key_data, value=value_data, thread_id=thread_id(),
883899
ttl=to_millis(ttl))
884900

901+
def _set_ttl_internal(self, key_data, ttl):
902+
return self._encode_invoke_on_key(map_set_ttl_codec, key_data, key=key_data, ttl=to_millis(ttl))
903+
885904
def _try_remove_internal(self, key_data, timeout):
886905
return self._encode_invoke_on_key(map_try_remove_codec, key_data, key=key_data, thread_id=thread_id(),
887906
timeout=to_millis(timeout))
@@ -1028,6 +1047,10 @@ def _set_internal(self, key_data, value_data, ttl):
10281047
self._invalidate_cache(key_data)
10291048
return super(MapFeatNearCache, self)._set_internal(key_data, value_data, ttl)
10301049

1050+
def _set_ttl_internal(self, key_data, ttl):
1051+
self._invalidate_cache(key_data)
1052+
return super(MapFeatNearCache, self)._set_ttl_internal(key_data, ttl)
1053+
10311054
def _replace_internal(self, key_data, value_data):
10321055
self._invalidate_cache(key_data)
10331056
return super(MapFeatNearCache, self)._replace_internal(key_data, value_data)

tests/proxy/map_test.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,15 @@ def test_set(self):
437437
self.map.set("key", "value")
438438

439439
self.assertEqual(self.map.get("key"), "value")
440+
441+
def test_set_ttl(self):
442+
self.map.put("key", "value")
443+
self.map.set_ttl("key", 0.1)
444+
445+
def evicted():
446+
self.assertFalse(self.map.contains_key("key"))
447+
448+
self.assertTrueEventually(evicted, 1)
440449

441450
def test_size(self):
442451
self._fill_map()

0 commit comments

Comments
 (0)