Skip to content

Commit

Permalink
Merge pull request #16 from BramSrna/implement_swarm_memory_update
Browse files Browse the repository at this point in the history
Implement swarm memory update
  • Loading branch information
BramSrna authored Mar 11, 2023
2 parents 09f78e9 + 170dde4 commit 4a64a80
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 24 deletions.
1 change: 1 addition & 0 deletions swarm/message_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ class MessageTypes(Enum):
BOT_TEARDOWN = 15
REQUEST_PATH_TO_BOT = 16
MSG_RESPONSE = 17
UPDATE_SWARM_MEMORY_VALUE = 18
10 changes: 10 additions & 0 deletions swarm/swarm_bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ def __init__(self, additional_config_path: str = None, additional_config_dict: d
self.assign_msg_handler(str(MessageTypes.BOT_TEARDOWN), self.handle_bot_teardown_message)
self.assign_msg_handler(str(MessageTypes.REQUEST_PATH_TO_BOT), self.handle_request_path_to_bot)
self.assign_msg_handler(str(MessageTypes.MSG_RESPONSE), self.handle_msg_response_message)
self.assign_msg_handler(str(MessageTypes.UPDATE_SWARM_MEMORY_VALUE), self.handle_update_swarm_memory_value)

def startup(self):
NetworkNode.startup(self)
Expand Down Expand Up @@ -107,6 +108,9 @@ def read_from_swarm_memory(self, key_to_read):
def write_to_swarm_memory(self, key_to_write, value_to_write, data_type):
self.swarm_memory_interface.write_to_swarm_memory(key_to_write, value_to_write, data_type)

def update_swarm_memory(self, key_to_update, new_value):
self.swarm_memory_interface.update_swarm_memory(key_to_update, new_value)

def get_task_execution_history(self):
return self.task_execution_history

Expand Down Expand Up @@ -391,6 +395,12 @@ def handle_msg_response_message(self, message):
with self.response_locks[original_message_id]["LOCK"]:
self.response_locks[original_message_id]["LOCK"].notify_all()

def handle_update_swarm_memory_value(self, message):
message_payload = message.get_message_payload()
key_to_update = message_payload["KEY_TO_UPDATE"]
new_value = message_payload["NEW_VALUE"]
self.update_swarm_memory(key_to_update, new_value)

def task_executor_loop(self):
while (not self.run_node.is_set()) and (not self.run_task_executor.is_set()):
self.task_queue_has_values.wait()
Expand Down
12 changes: 5 additions & 7 deletions swarm/swarm_memory/local_swarm_memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@ def __init__(self, owner_bot_id):
self.data_to_holder_id_map = {}

def write(self, new_key_to_write, new_value_to_write, data_type):
self.contents[new_key_to_write] = {
"DATA_TYPE": data_type,
"VALUE": new_value_to_write
}
self.contents[new_key_to_write] = new_value_to_write
self.update_data_holder(new_key_to_write, self.owner_bot_id, data_type)

def read(self, key_to_read):
if key_to_read in self.contents:
return self.contents[key_to_read]
return None

def update(self, key_to_update, new_value):
if self.has_data_key(key_to_update):
self.contents[key_to_update] = new_value

def delete(self, key_to_delete):
if key_to_delete in self.contents:
self.contents.pop(key_to_delete)
Expand All @@ -39,9 +40,6 @@ def get_data_holder_id(self, data_key):

def get_ids_of_contents_of_type(self, type_to_get):
ids = []
for data_key, data_info in self.contents.items():
if data_info["DATA_TYPE"] == type_to_get:
ids.append(data_key)
for data_key, data_info in self.data_to_holder_id_map.items():
if data_info["DATA_TYPE"] == type_to_get:
ids.append(data_key)
Expand Down
24 changes: 18 additions & 6 deletions swarm/swarm_memory/swarm_memory_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def read_from_swarm_memory(self, key_to_read):
bot_with_obj = self.local_swarm_memory.get_data_holder_id(key_to_read)
value = None
if bot_with_obj == self.executor_interface.get_id():
value = self.local_swarm_memory.read(key_to_read)["VALUE"]
value = self.local_swarm_memory.read(key_to_read)
elif bot_with_obj is not None:
response = self.executor_interface.send_sync_directed_message(
bot_with_obj,
Expand All @@ -31,11 +31,25 @@ def read_from_swarm_memory(self, key_to_read):
pass
return value

def update_swarm_memory(self, key_to_update, new_value):
bot_with_obj = self.local_swarm_memory.get_data_holder_id(key_to_update)
if bot_with_obj == self.executor_interface.get_id():
self.local_swarm_memory.update(key_to_update, new_value)
elif bot_with_obj is not None:
self.executor_interface.send_directed_message(
bot_with_obj,
MessageTypes.UPDATE_SWARM_MEMORY_VALUE,
{"KEY_TO_UPDATE": key_to_update, "NEW_VALUE": new_value}
)
else:
# else in this case means that the there is no key with the given value in the swarm memory
pass

def pop_from_swarm_memory(self, key_to_pop):
bot_with_obj = self.local_swarm_memory.get_data_holder_id(key_to_pop)
value = None
if bot_with_obj == self.executor_interface.get_id():
value = self.local_swarm_memory.read(key_to_pop)["VALUE"]
value = self.local_swarm_memory.read(key_to_pop)
self.local_swarm_memory.delete(key_to_pop)
self.executor_interface.send_propagation_message(
MessageTypes.DELETE_FROM_SWARM_MEMORY,
Expand Down Expand Up @@ -77,9 +91,7 @@ def handle_request_swarm_memory_read_message(self, message):
self.executor_interface.respond_to_message(
message,
{
"OBJECT_KEY": object_key,
"OBJECT_VALUE": object_info["VALUE"],
"DATA_TYPE": object_info["DATA_TYPE"]
"OBJECT_VALUE": object_info
}
)

Expand All @@ -93,7 +105,7 @@ def handle_pop_from_swarm_memory_message(self, message):
self.executor_interface.send_directed_message(
message.get_sender_id(),
MessageTypes.RESPOND_TO_READ,
{"OBJECT_KEY": key_to_pop, "OBJECT_VALUE": object_info["VALUE"], "DATA_TYPE": object_info["DATA_TYPE"]}
{"OBJECT_VALUE": object_info["VALUE"]}
)

self.local_swarm_memory.delete(key_to_pop)
Expand Down
86 changes: 75 additions & 11 deletions swarm_bot_test/test_swarm_bot_swarm_memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ def test_can_access_swarm_memory_when_info_stored_on_local_swarm_bot(self):

test_swarm_bot_1.write_to_swarm_memory(test_mem_id, test_mem_val, "str")

ret_val = test_swarm_bot_1.read_from_swarm_memory(test_mem_id)

self.assertEqual(test_mem_val, ret_val)
self.assertEqual(test_mem_val, test_swarm_bot_1.read_from_swarm_memory(test_mem_id))

def test_can_access_swarm_memory_when_info_stored_on_directly_connected_swarm_bot(self):
test_swarm_bot_1 = self.create_network_node(SwarmBot)
Expand All @@ -28,19 +26,15 @@ def test_can_access_swarm_memory_when_info_stored_on_directly_connected_swarm_bo
test_swarm_bot_2.startup()

test_swarm_bot_1.connect_to_network_node(test_swarm_bot_2)

self.wait_for_idle_network()

test_mem_id = "TEST_ID"
test_mem_val = "TEST_VAL"

test_swarm_bot_1.write_to_swarm_memory(test_mem_id, test_mem_val, "str")

self.wait_for_idle_network()

ret_val = test_swarm_bot_2.read_from_swarm_memory(test_mem_id)

self.assertEqual(test_mem_val, ret_val)
self.assertEqual(test_mem_val, test_swarm_bot_2.read_from_swarm_memory(test_mem_id))

def test_can_access_swarm_memory_when_info_stored_on_non_directly_connected_swarm_bot(self):
test_swarm_bot_1 = self.create_network_node(SwarmBot)
Expand All @@ -53,19 +47,89 @@ def test_can_access_swarm_memory_when_info_stored_on_non_directly_connected_swar

test_swarm_bot_1.connect_to_network_node(test_swarm_bot_2)
test_swarm_bot_2.connect_to_network_node(test_swarm_bot_3)

self.wait_for_idle_network()

test_mem_id = "TEST_ID"
test_mem_val = "TEST_VAL"

test_swarm_bot_1.write_to_swarm_memory(test_mem_id, test_mem_val, "str")
self.wait_for_idle_network()

self.assertEqual(test_mem_val, test_swarm_bot_3.read_from_swarm_memory(test_mem_id))

def test_can_update_swarm_memory_objects_when_info_stored_on_local_swarm_bot(self):
test_swarm_bot_1 = self.create_network_node(SwarmBot)

test_swarm_bot_1.startup()

test_mem_id = "TEST_ID"
original_val = "TEST_VAL_1"

test_swarm_bot_1.write_to_swarm_memory(test_mem_id, original_val, "str")

self.assertEqual(original_val, test_swarm_bot_1.read_from_swarm_memory(test_mem_id))

new_val = "TEST_VAL_2"

test_swarm_bot_1.update_swarm_memory(test_mem_id, new_val)

self.assertEqual(new_val, test_swarm_bot_1.read_from_swarm_memory(test_mem_id))

def test_can_update_swarm_memory_objects_when_info_stored_on_directly_connected_swarm_bot(self):
test_swarm_bot_1 = self.create_network_node(SwarmBot)
test_swarm_bot_2 = self.create_network_node(SwarmBot)

test_swarm_bot_1.startup()
test_swarm_bot_2.startup()

test_swarm_bot_1.connect_to_network_node(test_swarm_bot_2)
self.wait_for_idle_network()

ret_val = test_swarm_bot_3.read_from_swarm_memory(test_mem_id)
test_mem_id = "TEST_ID"
original_val = "TEST_VAL_1"

test_swarm_bot_1.write_to_swarm_memory(test_mem_id, original_val, "str")
self.wait_for_idle_network()

self.assertEqual(original_val, test_swarm_bot_2.read_from_swarm_memory(test_mem_id))

new_val = "TEST_VAL_2"

test_swarm_bot_2.update_swarm_memory(test_mem_id, new_val)
self.wait_for_idle_network()

self.assertEqual(new_val, test_swarm_bot_2.read_from_swarm_memory(test_mem_id))
self.assertEqual(new_val, test_swarm_bot_1.read_from_swarm_memory(test_mem_id))

def test_can_update_swarm_memory_objects_when_info_stored_on_non_directly_connected_swarm_bot(self):
test_swarm_bot_1 = self.create_network_node(SwarmBot)
test_swarm_bot_2 = self.create_network_node(SwarmBot)
test_swarm_bot_3 = self.create_network_node(SwarmBot)

test_swarm_bot_1.startup()
test_swarm_bot_2.startup()
test_swarm_bot_3.startup()

test_swarm_bot_1.connect_to_network_node(test_swarm_bot_2)
test_swarm_bot_2.connect_to_network_node(test_swarm_bot_3)
self.wait_for_idle_network()

test_mem_id = "TEST_ID"
original_val = "TEST_VAL_1"

test_swarm_bot_1.write_to_swarm_memory(test_mem_id, original_val, "str")
self.wait_for_idle_network()

self.assertEqual(original_val, test_swarm_bot_3.read_from_swarm_memory(test_mem_id))

new_val = "TEST_VAL_2"

test_swarm_bot_3.update_swarm_memory(test_mem_id, new_val)
self.wait_for_idle_network()

self.assertEqual(test_mem_val, ret_val)
self.assertEqual(new_val, test_swarm_bot_3.read_from_swarm_memory(test_mem_id))
self.assertEqual(new_val, test_swarm_bot_1.read_from_swarm_memory(test_mem_id))
self.assertEqual(new_val, test_swarm_bot_2.read_from_swarm_memory(test_mem_id))


if __name__ == "__main__":
Expand Down

0 comments on commit 4a64a80

Please sign in to comment.