def execute_on_members( self, members: typing.Sequence[MemberInfo], task: typing.Any) -> Future[typing.List[typing.Any]]: """Executes a task on each of the specified members. Args: members: The specified members. task: The task executed on the specified members. Returns: The list of results of the tasks on each member. """ try: task_data = self._to_data(task) except SchemaNotReplicatedError as e: return self._send_schema_and_retry(e, self.execute_on_members, members, task) futures = [] uuid = uuid4() for member in members: f = self._execute_on_member(uuid, task_data, member.uuid) futures.append(f) return future.combine_futures(futures)
def get_all(self, keys): check_not_none(keys, "keys can't be None") if not keys: return ImmediateFuture({}) partition_service = self._client.partition_service partition_to_keys = {} for key in keys: check_not_none(key, "key can't be None") key_data = self._to_data(key) partition_id = partition_service.get_partition_id(key_data) try: partition_to_keys[partition_id].append(key_data) except KeyError: partition_to_keys[partition_id] = [key_data] futures = [] for partition_id, key_list in partition_to_keys.iteritems(): future = self._encode_invoke_on_partition(map_get_all_codec, partition_id, keys=key_list) futures.append(future) def merge(f): return dict(itertools.chain(*f.result())) return combine_futures(*futures).continue_with(merge)
def put_all(self, map): check_not_none(map, "map can't be None") if not map: return ImmediateFuture(None) partition_service = self._client.partition_service partition_map = {} for key, value in map.iteritems(): check_not_none(key, "key can't be None") check_not_none(value, "value can't be None") entry = (self._to_data(key), self._to_data(value)) partition_id = partition_service.get_partition_id(entry[0]) try: partition_map[partition_id].append(entry) except KeyError: partition_map[partition_id] = [entry] futures = [] for partition_id, entry_list in partition_map.iteritems(): future = self._encode_invoke_on_partition(map_put_all_codec, partition_id, entries=dict(entry_list)) futures.append(future) return combine_futures(*futures)
def register_listener(self, registration_request, decode_register_response, encode_deregister_request, handler): with self._registration_lock: registration_id = str(uuid4()) registration = _ListenerRegistration(registration_request, decode_register_response, encode_deregister_request, handler) self._active_registrations[registration_id] = registration futures = [] for connection in list( six.itervalues( self._connection_manager.active_connections)): future = self._register_on_connection(registration_id, registration, connection) futures.append(future) def handler(f): try: f.result() return registration_id except: self.deregister_listener(registration_id) raise HazelcastError("Listener cannot be added") return combine_futures(futures).continue_with(handler)
def execute_on_members(self, members, task): task_data = self._to_data(task) futures = [] uuid = self._get_uuid() for member in members: f = self._execute_on_member(member.address, uuid, task_data) futures.append(f) return future.combine_futures(*futures)
def test_combine_futures_exception(self): f1, f2, f3 = Future(), Future(), Future() combined = combine_futures([f1, f2, f3]) e = RuntimeError("error") f1.set_result("done") f2.set_result("done") f3.set_exception(e) self.assertEqual(e, combined.exception())
def _get_all_internal(self, partition_to_keys, futures=None): if futures is None: futures = [] for partition_id, key_dict in partition_to_keys.iteritems(): future = self._encode_invoke_on_partition(map_get_all_codec, partition_id, keys=key_dict.values()) futures.append(future) def merge(f): return dict(itertools.chain(*f.result())) return combine_futures(*futures).continue_with(merge)
def test_combine_futures_exception(self): f1, f2, f3 = Future(), Future(), Future() combined = combine_futures(f1, f2, f3) e = RuntimeError("error") f1.set_result("done") f2.set_result("done") f3.set_exception(e) self.assertEqual(e, combined.exception())
def test_completion_order(self): # Verifies that the returned list order is # consistent with the order of input futures # regardless of the completion order of futures. f1, f2, f3 = Future(), Future(), Future() combined = combine_futures([f1, f2, f3]) f3.set_result(3) f1.set_result(1) f2.set_result(2) self.assertEqual([1, 2, 3], combined.result())
def deregister_listener(self, user_registration_id): check_not_none(user_registration_id, "None user_registration_id is not allowed!") with self._registration_lock: listener_registration = self._active_registrations.pop( user_registration_id, None) if not listener_registration: return ImmediateFuture(False) futures = [] for ( connection, event_registration, ) in listener_registration.connection_registrations.items(): # Remove local handler self.remove_event_handler(event_registration.correlation_id) # The rest is for deleting the remote registration server_registration_id = event_registration.server_registration_id deregister_request = listener_registration.encode_deregister_request( server_registration_id) if deregister_request is None: # None means no remote registration (e.g. for backup acks) continue invocation = Invocation(deregister_request, connection=connection, timeout=sys.maxsize, urgent=True) self._invocation_service.invoke(invocation) def handler(f, captured_connection=connection): e = f.exception() if not e: return if isinstance(e, (HazelcastClientNotActiveError, IOError, TargetDisconnectedError)): return _logger.warning( "Deregistration of listener with ID %s has failed for address %s: %s", user_registration_id, captured_connection.remote_address, e, ) invocation.future.add_done_callback(handler) futures.append(invocation.future) listener_registration.connection_registrations.clear() return combine_futures(futures).continue_with(lambda _: True)
def test_combine_futures(self): f1, f2, f3 = Future(), Future(), Future() combined = combine_futures([f1, f2, f3]) f1.set_result("done1") self.assertFalse(combined.done()) f2.set_result("done2") self.assertFalse(combined.done()) f3.set_result("done3") self.assertEqual(combined.result(), ["done1", "done2", "done3"])
def test_combine_futures(self): f1, f2, f3 = Future(), Future(), Future() combined = combine_futures(f1, f2, f3) f1.set_result("done1") self.assertFalse(combined.done()) f2.set_result("done2") self.assertFalse(combined.done()) f3.set_result("done3") self.assertEqual(combined.result(), ["done1", "done2", "done3"])
def test_waiting_for_all_inputs(self): # Verifies that we wait for all futures, even if some # of them fails. f1, f2, f3 = Future(), Future(), Future() combined = combine_futures([f1, f2, f3]) e = RuntimeError("expected") f1.set_exception(e) self.assertFalse(combined.done()) f2.set_result(1) self.assertFalse(combined.done()) f3.set_result(2) self.assertTrue(combined.done()) self.assertFalse(combined.is_success()) self.assertEqual(e, combined.exception())
def execute_on_members(self, members, task): """ Executes a task on each of the specified members. :param members: (Collection), the specified members. :param task: (Task), the task executed on the specified members. :return: (Map), :class:`~hazelcast.future.Future` tuples representing pending completion of the task on each member. """ task_data = self._to_data(task) futures = [] uuid = self._get_uuid() for member in members: f = self._execute_on_member(member.address, uuid, task_data) futures.append(f) return future.combine_futures(*futures)
def test_returning_first_error(self): # Verifies that we return the first error occurred, even # if more than one of the input futures completed # exceptionally. f1, f2, f3 = Future(), Future(), Future() combined = combine_futures([f1, f2, f3]) e1 = RuntimeError("expected") f1.set_exception(e1) self.assertFalse(combined.done()) e2 = RuntimeError("expected2") f2.set_exception(e2) self.assertFalse(combined.done()) e3 = RuntimeError("expected3") f3.set_exception(e3) self.assertTrue(combined.done()) self.assertFalse(combined.is_success()) self.assertEqual(e1, combined.exception())
def execute_on_members(self, members, task): """Executes a task on each of the specified members. Args: members (list[hazelcast.core.MemberInfo]): The specified members. task: The task executed on the specified members. Returns: list[hazelcast.future.Future]: Futures representing pending completion of the task on each member. """ task_data = self._to_data(task) futures = [] uuid = uuid4() for member in members: f = self._execute_on_member(uuid, task_data, member.uuid) futures.append(f) return future.combine_futures(futures)
def shutdown(self): with self._lock: if self._shutdown: return ImmediateFuture(None) self._shutdown = True if self._heartbeat_timer: self._heartbeat_timer.cancel() futures = [] for session in list(self._sessions.values()): future = self._request_close_session(session.group_id, session.id) futures.append(future) def clear(_): self._sessions.clear() self._mutexes.clear() self._thread_ids.clear() return combine_futures(futures).continue_with(clear)
def test_combine_futures_with_empty_list(self): combined = combine_futures([]) self.assertTrue(combined.done()) self.assertEqual([], combined.result())
def test_empty_input(self): combined = combine_futures([]) self.assertTrue(combined.done()) self.assertEqual([], combined.result())