Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions hazelcast/protocol/codec/map_remove_interceptor_codec.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from hazelcast.protocol.builtin import FixSizedTypesCodec
from hazelcast.protocol.client_message import OutboundMessage, REQUEST_HEADER_SIZE, create_initial_buffer, RESPONSE_HEADER_SIZE
from hazelcast.protocol.builtin import StringCodec

# hex: 0x011500
_REQUEST_MESSAGE_TYPE = 70912
# hex: 0x011501
_RESPONSE_MESSAGE_TYPE = 70913

_REQUEST_INITIAL_FRAME_SIZE = REQUEST_HEADER_SIZE
_RESPONSE_RESPONSE_OFFSET = RESPONSE_HEADER_SIZE


def encode_request(name, id):
buf = create_initial_buffer(_REQUEST_INITIAL_FRAME_SIZE, _REQUEST_MESSAGE_TYPE)
StringCodec.encode(buf, name)
StringCodec.encode(buf, id, True)
return OutboundMessage(buf, False)


def decode_response(msg):
initial_frame = msg.next_frame()
return FixSizedTypesCodec.decode_boolean(initial_frame.buf, _RESPONSE_RESPONSE_OFFSET)
16 changes: 16 additions & 0 deletions hazelcast/proxy/map.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
map_put_if_absent_with_max_idle_codec,
map_put_transient_with_max_idle_codec,
map_set_with_max_idle_codec,
map_remove_interceptor_codec,
)
from hazelcast.proxy.base import (
Proxy,
Expand Down Expand Up @@ -1086,6 +1087,21 @@ def remove_entry_listener(self, registration_id):
"""
return self._deregister_listener(registration_id)

def remove_interceptor(self, registration_id):
"""Removes the given interceptor for this map, so it will not intercept
operations anymore.

Args:
registration_id (str): Registration ID of the map interceptor.

Returns:
hazelcast.future.Future[bool]: ``True`` if the interceptor is
removed, ``False`` otherwise.
"""
check_not_none(registration_id, "Interceptor registration id should not be None")
request = map_remove_interceptor_codec.encode_request(self.name, registration_id)
return self._invoke(request, map_remove_interceptor_codec.decode_response)

def replace(self, key, value):
"""Replaces the entry for a key only if it is currently mapped to some value.

Expand Down
46 changes: 46 additions & 0 deletions tests/integration/backward_compatible/proxy/map_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,27 @@ def get_class_id(self):
return self.CLASS_ID


class MapGetInterceptor(IdentifiedDataSerializable):

FACTORY_ID = 666
CLASS_ID = 6

def __init__(self, prefix):
self.prefix = prefix

def write_data(self, object_data_output):
write_string_to_output(object_data_output, self.prefix)

def read_data(self, object_data_input):
pass

def get_factory_id(self):
return self.FACTORY_ID

def get_class_id(self):
return self.CLASS_ID


class MapTest(SingleMemberTestCase):
@classmethod
def configure_cluster(cls):
Expand Down Expand Up @@ -596,6 +617,31 @@ def test_values_with_predicate(self):
def test_str(self):
self.assertTrue(str(self.map).startswith("Map"))

def test_add_interceptor(self):
interceptor = MapGetInterceptor(":")
registration_id = self.map.add_interceptor(interceptor)
self.assertIsNotNone(registration_id)

self.map.set(1, ")")
value = self.map.get(1)
self.assertEqual(":)", value)

def test_remove_interceptor(self):
skip_if_client_version_older_than(self, "5.0")

interceptor = MapGetInterceptor(":")
registration_id = self.map.add_interceptor(interceptor)
self.assertIsNotNone(registration_id)
self.assertTrue(self.map.remove_interceptor(registration_id))

# Unknown registration id should return False
self.assertFalse(self.map.remove_interceptor(registration_id))

# Make sure that the interceptor is indeed removed
self.map.set(1, ")")
value = self.map.get(1)
self.assertEqual(")", value)

def fill_map(self, count=10):
m = {"key-%d" % x: "value-%d" % x for x in range(0, count)}
self.map.put_all(m)
Expand Down