diff --git a/jac-cloud/jac_cloud/core/memory.py b/jac-cloud/jac_cloud/core/memory.py index 2439b0486c..e7deea840f 100644 --- a/jac-cloud/jac_cloud/core/memory.py +++ b/jac-cloud/jac_cloud/core/memory.py @@ -114,23 +114,14 @@ def close(self) -> None: super().close() - def get_bulk_write(self) -> BulkWrite: - """Sync memory to database.""" - bulk_write = BulkWrite() - - for anchor in self.__gc__: - match anchor: - case NodeAnchor(): - bulk_write.del_node(anchor.id) - case EdgeAnchor(): - bulk_write.del_edge(anchor.id) - case WalkerAnchor(): - bulk_write.del_walker(anchor.id) - case _: - pass - - for anchor in self.__mem__.values(): - if anchor.architype and anchor.persistent: + def sync_mem_to_db(self, bulk_write: BulkWrite, keys: Iterable[ObjectId]) -> None: + """Manually sync memory to db.""" + for key in keys: + if ( + (anchor := self.__mem__.get(key)) + and anchor.architype + and anchor.persistent + ): if not anchor.state.connected: anchor.state.connected = True anchor.sync_hash() @@ -151,4 +142,27 @@ def get_bulk_write(self) -> BulkWrite: else: anchor.update(bulk_write) + def get_bulk_write(self) -> BulkWrite: + """Sync memory to database.""" + bulk_write = BulkWrite() + + for anchor in self.__gc__: + match anchor: + case NodeAnchor(): + bulk_write.del_node(anchor.id) + case EdgeAnchor(): + bulk_write.del_edge(anchor.id) + case WalkerAnchor(): + bulk_write.del_walker(anchor.id) + case _: + pass + + keys = set(self.__mem__.keys()) + + # current memory + self.sync_mem_to_db(bulk_write, keys) + + # additional after memory sync + self.sync_mem_to_db(bulk_write, set(self.__mem__.keys() - keys)) + return bulk_write diff --git a/jac-cloud/jac_cloud/tests/openapi_specs.yaml b/jac-cloud/jac_cloud/tests/openapi_specs.yaml index 7881a6fd12..dc4a2f15af 100644 --- a/jac-cloud/jac_cloud/tests/openapi_specs.yaml +++ b/jac-cloud/jac_cloud/tests/openapi_specs.yaml @@ -382,6 +382,15 @@ components: - root_id title: allow_other_root_access_body_model type: object + check_memory_sync_body_model: + properties: + other_node_id: + title: Other Node Id + type: string + required: + - other_node_id + title: check_memory_sync_body_model + type: object combination1_body_model: properties: c: @@ -841,6 +850,77 @@ paths: tags: - walker - walker + /walker/check_memory_sync: + post: + operationId: api_root_walker_check_memory_sync_post + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/check_memory_sync_body_model' + required: true + responses: + '200': + content: + application/json: + schema: + anyOf: + - $ref: '#/components/schemas/ContextResponse_NoneType_' + - {} + title: Response Api Root Walker Check Memory Sync Post + description: Successful Response + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPValidationError' + description: Validation Error + security: + - HTTPBearer: [] + summary: /check_memory_sync + tags: + - walker + - walker + /walker/check_memory_sync/{node}: + post: + operationId: api_entry_walker_check_memory_sync__node__post + parameters: + - in: path + name: node + required: true + schema: + anyOf: + - type: string + - type: 'null' + title: Node + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/check_memory_sync_body_model' + required: true + responses: + '200': + content: + application/json: + schema: + anyOf: + - $ref: '#/components/schemas/ContextResponse_NoneType_' + - {} + title: Response Api Entry Walker Check Memory Sync Node Post + description: Successful Response + '422': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPValidationError' + description: Validation Error + security: + - HTTPBearer: [] + summary: /check_memory_sync/{node} + tags: + - walker + - walker /walker/check_populated_graph: post: operationId: api_root_walker_check_populated_graph_post diff --git a/jac-cloud/jac_cloud/tests/simple_graph.jac b/jac-cloud/jac_cloud/tests/simple_graph.jac index 1a8fb913b6..846289d4fa 100644 --- a/jac-cloud/jac_cloud/tests/simple_graph.jac +++ b/jac-cloud/jac_cloud/tests/simple_graph.jac @@ -710,4 +710,14 @@ walker check_populated_graph { report count; } +} + +walker check_memory_sync { + has other_node_id: str; + can enter with `root entry { + import:py from jac_cloud.core.architype {NodeAnchor} + n = &(self.other_node_id); + n.val = 4; + report n; + } } \ No newline at end of file diff --git a/jac-cloud/jac_cloud/tests/test_simple_graph.py b/jac-cloud/jac_cloud/tests/test_simple_graph.py index 91ac9111f8..9f9fadc851 100644 --- a/jac-cloud/jac_cloud/tests/test_simple_graph.py +++ b/jac-cloud/jac_cloud/tests/test_simple_graph.py @@ -560,19 +560,19 @@ def trigger_upload_file(self) -> None: "single": { "name": "simple_graph.jac", "content_type": "application/octet-stream", - "size": 15146, + "size": 15376, } }, "multiple": [ { "name": "simple_graph.jac", "content_type": "application/octet-stream", - "size": 15146, + "size": 15376, }, { "name": "simple_graph.jac", "content_type": "application/octet-stream", - "size": 15146, + "size": 15376, }, ], "singleOptional": None, @@ -620,6 +620,22 @@ def trigger_reset_graph(self) -> None: self.assertEqual([None], res["returns"]) self.assertEqual([1], res["reports"]) + def trigger_memory_sync(self) -> None: + """Test memory sync.""" + res = self.post_api("traverse_graph") + + self.assertEqual(200, res["status"]) + self.assertEqual([None, None, None], res["returns"]) + + a_node = res["reports"].pop(1) + self.assertTrue(a_node["id"].startswith("n:A:")) + self.assertEqual({"val": 1}, a_node["context"]) + + res = self.post_api( + "check_memory_sync", json={"other_node_id": a_node["id"]}, user=1 + ) + self.assertEqual(200, res["status"]) + def test_all_features(self) -> None: """Test Full Features.""" self.trigger_openapi_specs_test() @@ -716,3 +732,9 @@ def test_all_features(self) -> None: ################################################### self.trigger_reset_graph() + + ################################################### + # TEST MEMORY SYNC # + ################################################### + + self.trigger_memory_sync() diff --git a/jac-cloud/scripts/v1-to-v2.js b/jac-cloud/scripts/v1-to-v2.js index c99c8bce69..3a269a4597 100644 --- a/jac-cloud/scripts/v1-to-v2.js +++ b/jac-cloud/scripts/v1-to-v2.js @@ -1,11 +1,10 @@ -use jaclang; +use jaseci; for (let c of ["node", "edge", "walker"]) { var col = db[c]; col.find().forEach(row => { var roots = {}, access = { "roots": { - "whitelist": true, "anchors": roots } }; @@ -20,6 +19,15 @@ for (let c of ["node", "edge", "walker"]) { access["all"] = "NO_ACCESS" } + var set = { "access": access }, + rename = { "edge": "edges" }; + + if (!row.context) { + set["architype"] = {}; + } else { + rename["context"] = "architype"; + } + for (let root of row.access.roots[0]) { roots["n::" + root.toString()] = "READ"; } @@ -28,11 +36,10 @@ for (let c of ["node", "edge", "walker"]) { roots["n::" + root.toString()] = "WRITE"; } + col.update({ _id: row._id }, { - "$rename": { "context": "architype", "edge": "edges" }, - "$set": { - "access": access - } + "$rename": rename, + "$set": set }); }) } \ No newline at end of file diff --git a/jac-cloud/setup.py b/jac-cloud/setup.py index 9b946b4eea..eea0ec032f 100644 --- a/jac-cloud/setup.py +++ b/jac-cloud/setup.py @@ -2,7 +2,7 @@ from setuptools import find_packages, setup -VERSION = "0.1.10" +VERSION = "0.1.11" setup( name="jac-cloud",