diff --git a/asyncua/server/internal_session.py b/asyncua/server/internal_session.py index 21d90366..a477185a 100644 --- a/asyncua/server/internal_session.py +++ b/asyncua/server/internal_session.py @@ -37,6 +37,7 @@ class InternalSession: self.state = SessionState.Created self.session_id = ua.NodeId(self._counter) InternalSession._counter += 1 + self.subscriptions = [] self.auth_token = ua.NodeId(self._auth_counter) InternalSession._auth_counter += 1 self.logger.info('Created internal session %s', self.name) @@ -63,7 +64,7 @@ class InternalSession: async def close_session(self, delete_subs=True): self.logger.info('close session %s', self.name) self.state = SessionState.Closed - await self.delete_subscriptions(list(self.subscription_service.subscriptions.keys())) + await self.delete_subscriptions(self.subscriptions) def activate_session(self, params): self.logger.info('activate session') @@ -119,6 +120,7 @@ class InternalSession: async def create_subscription(self, params, callback=None): result = await self.subscription_service.create_subscription(params, callback) + self.subscriptions.append(result.SubscriptionId) return result async def create_monitored_items(self, params: ua.CreateMonitoredItemsParameters): diff --git a/dev_requirements.txt b/dev_requirements.txt index 629777ea..0886edb7 100644 --- a/dev_requirements.txt +++ b/dev_requirements.txt @@ -1,3 +1,4 @@ pytest pytest-asyncio coverage +pytest-cov diff --git a/tests/test_server.py b/tests/test_server.py index 2d0b4118..ceb1100c 100644 --- a/tests/test_server.py +++ b/tests/test_server.py @@ -106,6 +106,31 @@ async def test_historize_variable(server): await var.set_value(3.0) await server.iserver.disable_history_data_change(var) +async def test_multiple_clients_with_subscriptions(server): + """ + Tests that multiple clients can subscribe, and when one client disconnects, the other + still maintains it's subscription + """ + class SubscriptionHandler: + def datachange_notification(self, node, val, data): + pass + sub_handler = SubscriptionHandler() + client1 = Client(server.endpoint.geturl()) + client2 = Client(server.endpoint.geturl()) + + o = server.get_objects_node() + var = await o.add_variable(3, "some_variable", 1.0) + async with client1: + async with client2: + sub1 = await client1.create_subscription(100, sub_handler) + sub2 = await client2.create_subscription(100, sub_handler) + await sub1.subscribe_data_change(var) + await sub2.subscribe_data_change(var) + assert len(server.iserver.subscription_service.subscriptions) == 2 + # When client2 disconnects, client1 should still keep it's subscription. + assert len(server.iserver.subscription_service.subscriptions) == 1 + assert len(server.iserver.subscription_service.subscriptions) == 0 + async def test_historize_events(server): srv_node = server.get_node(ua.ObjectIds.Server)