dasf-broker-django 0.0.1.dev0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dasf_broker/__init__.py +26 -0
- dasf_broker/_version.py +21 -0
- dasf_broker/admin.py +273 -0
- dasf_broker/app_settings.py +133 -0
- dasf_broker/apps.py +16 -0
- dasf_broker/constants.py +31 -0
- dasf_broker/consumers.py +269 -0
- dasf_broker/jobs/__init__.py +0 -0
- dasf_broker/jobs/minutely/__init__.py +0 -0
- dasf_broker/jobs/minutely/garbage_collect_topics.py +17 -0
- dasf_broker/jobs/minutely/ping_topics.py +19 -0
- dasf_broker/management/__init__.py +0 -0
- dasf_broker/management/commands/__init__.py +0 -0
- dasf_broker/management/commands/dasf_topic.py +353 -0
- dasf_broker/migrations/0001_initial.py +169 -0
- dasf_broker/migrations/0002_auto_20230213_1501.py +134 -0
- dasf_broker/migrations/__init__.py +0 -0
- dasf_broker/models.py +450 -0
- dasf_broker/py.typed +0 -0
- dasf_broker/routing.py +31 -0
- dasf_broker/templates/dasf_broker/payload_str.html +7 -0
- dasf_broker/templatetags/__init__.py +10 -0
- dasf_broker/templatetags/dasf.py +71 -0
- dasf_broker/tests/__init__.py +5 -0
- dasf_broker/tests/live_ws_server_helper.py +94 -0
- dasf_broker/tests/plugin.py +187 -0
- dasf_broker/token_auth_middleware.py +57 -0
- dasf_broker/urls.py +44 -0
- dasf_broker/views.py +87 -0
- dasf_broker_django-0.0.1.dev0.dist-info/METADATA +156 -0
- dasf_broker_django-0.0.1.dev0.dist-info/RECORD +38 -0
- dasf_broker_django-0.0.1.dev0.dist-info/WHEEL +5 -0
- dasf_broker_django-0.0.1.dev0.dist-info/entry_points.txt +2 -0
- dasf_broker_django-0.0.1.dev0.dist-info/licenses/LICENSES/Apache-2.0.txt +73 -0
- dasf_broker_django-0.0.1.dev0.dist-info/licenses/LICENSES/CC-BY-4.0.txt +156 -0
- dasf_broker_django-0.0.1.dev0.dist-info/licenses/LICENSES/CC0-1.0.txt +121 -0
- dasf_broker_django-0.0.1.dev0.dist-info/licenses/LICENSES/EUPL-1.2.txt +190 -0
- dasf_broker_django-0.0.1.dev0.dist-info/top_level.txt +1 -0
dasf_broker/__init__.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2022-2025 Helmholtz-Zentrum hereon GmbH
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: EUPL-1.2
|
|
4
|
+
|
|
5
|
+
"""Django-based Message Broker for DASF
|
|
6
|
+
|
|
7
|
+
A Django-based message broker for the Data Analytics Software Framework (DASF)
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from . import _version
|
|
13
|
+
|
|
14
|
+
__version__ = _version.get_versions()["version"]
|
|
15
|
+
|
|
16
|
+
__author__ = "Philipp S. Sommer"
|
|
17
|
+
__copyright__ = "Copyright (C) 2022 Helmholtz-Zentrum Hereon"
|
|
18
|
+
__credits__ = [
|
|
19
|
+
"Philipp S. Sommer",
|
|
20
|
+
]
|
|
21
|
+
__license__ = "EUPL-1.2"
|
|
22
|
+
|
|
23
|
+
__maintainer__ = "Helmholtz-Zentrum Hereon"
|
|
24
|
+
__email__ = "hcdc_support@hereon.de"
|
|
25
|
+
|
|
26
|
+
__status__ = "Pre-Alpha"
|
dasf_broker/_version.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
|
|
2
|
+
# This file was generated by 'versioneer.py' (0.29) from
|
|
3
|
+
# revision-control system data, or from the parent directory name of an
|
|
4
|
+
# unpacked source archive. Distribution tarballs contain a pre-generated copy
|
|
5
|
+
# of this file.
|
|
6
|
+
|
|
7
|
+
import json
|
|
8
|
+
|
|
9
|
+
version_json = '''
|
|
10
|
+
{
|
|
11
|
+
"date": "2025-04-16T22:10:07+0200",
|
|
12
|
+
"dirty": false,
|
|
13
|
+
"error": null,
|
|
14
|
+
"full-revisionid": "b5fb8bd0d75756eb7c531bba7b50a9d73401626b",
|
|
15
|
+
"version": "0.0.1.dev0"
|
|
16
|
+
}
|
|
17
|
+
''' # END VERSION_JSON
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def get_versions():
|
|
21
|
+
return json.loads(version_json)
|
dasf_broker/admin.py
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2022-2025 Helmholtz-Zentrum hereon GmbH
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: EUPL-1.2
|
|
4
|
+
|
|
5
|
+
"""Admin interfaces
|
|
6
|
+
----------------
|
|
7
|
+
|
|
8
|
+
This module defines the dasf-broker-django
|
|
9
|
+
Admin interfaces.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
from typing import TYPE_CHECKING, Any, List, Optional, Tuple
|
|
15
|
+
|
|
16
|
+
from django.contrib import admin # noqa: F401
|
|
17
|
+
from django.utils.timezone import now
|
|
18
|
+
from guardian.admin import GuardedModelAdmin
|
|
19
|
+
|
|
20
|
+
from dasf_broker import models # noqa: F401
|
|
21
|
+
|
|
22
|
+
if TYPE_CHECKING:
|
|
23
|
+
from django.db.models import QuerySet
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ResponseTopicExistsFilter(admin.SimpleListFilter):
|
|
27
|
+
"""Filter topics for response topics"""
|
|
28
|
+
|
|
29
|
+
title = "is response topic"
|
|
30
|
+
|
|
31
|
+
parameter_name = "responsetopic"
|
|
32
|
+
|
|
33
|
+
def lookups(self, request: Any, model_admin: Any) -> List[Tuple[Any, str]]:
|
|
34
|
+
return [("1", "Yes"), ("0", "No")]
|
|
35
|
+
|
|
36
|
+
def queryset(
|
|
37
|
+
self, request: Any, queryset: QuerySet[Any]
|
|
38
|
+
) -> Optional[QuerySet[Any]]:
|
|
39
|
+
value = self.value()
|
|
40
|
+
if value == "1":
|
|
41
|
+
return queryset.filter(responsetopic__isnull=False)
|
|
42
|
+
elif value == "0":
|
|
43
|
+
return queryset.filter(responsetopic__isnull=True)
|
|
44
|
+
else:
|
|
45
|
+
return queryset
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class AvailabilityFilter(admin.SimpleListFilter):
|
|
49
|
+
"""Filter topics based on their status."""
|
|
50
|
+
|
|
51
|
+
title = "Availability"
|
|
52
|
+
|
|
53
|
+
parameter_name = "last_pong"
|
|
54
|
+
|
|
55
|
+
def lookups(self, request: Any, model_admin: Any) -> List[Tuple[Any, str]]:
|
|
56
|
+
return [
|
|
57
|
+
("offline", "Offline"),
|
|
58
|
+
("online", "Online"),
|
|
59
|
+
("unknown", "Unknown"),
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
def queryset( # type: ignore
|
|
63
|
+
self,
|
|
64
|
+
request: Any,
|
|
65
|
+
queryset: models.BrokerTopicQuerySet, # type: ignore
|
|
66
|
+
) -> Optional[QuerySet[Any]]:
|
|
67
|
+
value = self.value()
|
|
68
|
+
if value == "offline":
|
|
69
|
+
return queryset.filter_offline()
|
|
70
|
+
elif value == "online":
|
|
71
|
+
return queryset.filter_online()
|
|
72
|
+
elif value == "unknown":
|
|
73
|
+
return queryset.filter_unknown_availability()
|
|
74
|
+
else:
|
|
75
|
+
return queryset
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@admin.action(description="Ping topics")
|
|
79
|
+
def ping_topics(modeladmin, request, queryset):
|
|
80
|
+
"""Ping the broker topics."""
|
|
81
|
+
for topic in queryset.filter(supports_dasf=True):
|
|
82
|
+
topic.ping()
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
@admin.action(description="Garbage collect topics")
|
|
86
|
+
def garbage_collect(modeladmin, request, queryset):
|
|
87
|
+
queryset.filter(garbage_collect_on__lte=now()).delete()
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@admin.register(models.BrokerTopic)
|
|
91
|
+
class BrokerTopicAdmin(GuardedModelAdmin):
|
|
92
|
+
"""An admin for :model:`dasf_broker.BrokerTopic"""
|
|
93
|
+
|
|
94
|
+
search_fields = [
|
|
95
|
+
"slug__icontains",
|
|
96
|
+
]
|
|
97
|
+
|
|
98
|
+
list_display = [
|
|
99
|
+
"slug",
|
|
100
|
+
"get_consumers",
|
|
101
|
+
"get_producers",
|
|
102
|
+
"is_public",
|
|
103
|
+
"is_response_topic",
|
|
104
|
+
"get_availability",
|
|
105
|
+
"pending_messages",
|
|
106
|
+
"stored_messages",
|
|
107
|
+
"stored_responses",
|
|
108
|
+
]
|
|
109
|
+
|
|
110
|
+
list_filter = [
|
|
111
|
+
"is_public",
|
|
112
|
+
"date_created",
|
|
113
|
+
ResponseTopicExistsFilter,
|
|
114
|
+
AvailabilityFilter,
|
|
115
|
+
]
|
|
116
|
+
|
|
117
|
+
actions = [ping_topics, garbage_collect]
|
|
118
|
+
|
|
119
|
+
@admin.display(description="Consumer(s)") # type: ignore
|
|
120
|
+
def get_consumers(self, obj: models.BrokerTopic) -> str:
|
|
121
|
+
return ", ".join(map(str, obj.consumers))[:60]
|
|
122
|
+
|
|
123
|
+
@admin.display(description="Producer(s)") # type: ignore
|
|
124
|
+
def get_producers(self, obj: models.BrokerTopic) -> str:
|
|
125
|
+
return ", ".join(map(str, obj.producers))[:60]
|
|
126
|
+
|
|
127
|
+
@admin.display(boolean=True) # type: ignore
|
|
128
|
+
def is_response_topic(self, obj: models.BrokerTopic) -> bool:
|
|
129
|
+
return obj.is_response_topic
|
|
130
|
+
|
|
131
|
+
@admin.display(description="Online?", boolean=True) # type: ignore
|
|
132
|
+
def get_availability(self, obj: models.BrokerTopic) -> Optional[bool]:
|
|
133
|
+
return obj.availability
|
|
134
|
+
|
|
135
|
+
def pending_messages(self, obj: models.BrokerTopic) -> str:
|
|
136
|
+
"""Get the number of messages that have not yet been delivered"""
|
|
137
|
+
return str(obj.brokermessage_set.filter(delivered_to=None).count())
|
|
138
|
+
|
|
139
|
+
def stored_messages(self, obj: models.BrokerTopic) -> str:
|
|
140
|
+
"""Get the number of messages in the database."""
|
|
141
|
+
return str(obj.brokermessage_set.count())
|
|
142
|
+
|
|
143
|
+
def stored_responses(self, obj: models.BrokerTopic) -> str:
|
|
144
|
+
"""Get the number of messages in the database."""
|
|
145
|
+
if obj.is_response_topic:
|
|
146
|
+
return "-"
|
|
147
|
+
else:
|
|
148
|
+
return str(
|
|
149
|
+
models.BrokerMessage.objects.filter(
|
|
150
|
+
topic__responsetopic__is_response_for=obj
|
|
151
|
+
).count()
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
@admin.register(models.ResponseTopic)
|
|
156
|
+
class ResponseTopicAdmin(BrokerTopicAdmin):
|
|
157
|
+
"""An admin for response topics."""
|
|
158
|
+
|
|
159
|
+
search_fields = BrokerTopicAdmin.search_fields + [
|
|
160
|
+
"is_response_for__slug__icontains"
|
|
161
|
+
]
|
|
162
|
+
|
|
163
|
+
list_display = BrokerTopicAdmin.list_display[:-1]
|
|
164
|
+
|
|
165
|
+
list_filter = [
|
|
166
|
+
"is_public",
|
|
167
|
+
"date_created",
|
|
168
|
+
]
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
@admin.action(description="Send messages")
|
|
172
|
+
def send_messages(modeladmin, request, queryset):
|
|
173
|
+
for message in queryset:
|
|
174
|
+
message.send()
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
@admin.action(description="Ping topics")
|
|
178
|
+
def ping_message_topics(modeladmin, request, queryset):
|
|
179
|
+
pks = queryset.values_list("topic__pk", flat=True)
|
|
180
|
+
for topic in models.BrokerTopic.objects.filter(
|
|
181
|
+
pk__in=pks, supports_dasf=True
|
|
182
|
+
):
|
|
183
|
+
topic.ping()
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
class IsResponseMessageFilter(admin.SimpleListFilter):
|
|
187
|
+
"""Filter broker messages to a response topic"""
|
|
188
|
+
|
|
189
|
+
title = "is response message"
|
|
190
|
+
|
|
191
|
+
parameter_name = "topic"
|
|
192
|
+
|
|
193
|
+
def lookups(self, request: Any, model_admin: Any) -> List[Tuple[Any, str]]:
|
|
194
|
+
return [("1", "Yes"), ("0", "No")]
|
|
195
|
+
|
|
196
|
+
def queryset(
|
|
197
|
+
self, request: Any, queryset: QuerySet[Any]
|
|
198
|
+
) -> Optional[QuerySet[Any]]:
|
|
199
|
+
value = self.value()
|
|
200
|
+
if value == "1":
|
|
201
|
+
return queryset.filter(topic__responsetopic__isnull=False)
|
|
202
|
+
elif value == "0":
|
|
203
|
+
return queryset.filter(topic__responsetopic__isnull=True)
|
|
204
|
+
else:
|
|
205
|
+
return queryset
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
class HasBeenDeliveredFilter(admin.SimpleListFilter):
|
|
209
|
+
"""Filter broker messages by their delivery state"""
|
|
210
|
+
|
|
211
|
+
title = "has been delivered"
|
|
212
|
+
|
|
213
|
+
parameter_name = "delivered_to"
|
|
214
|
+
|
|
215
|
+
def lookups(self, request: Any, model_admin: Any) -> List[Tuple[Any, str]]:
|
|
216
|
+
return [("1", "Yes"), ("0", "No")]
|
|
217
|
+
|
|
218
|
+
def queryset(
|
|
219
|
+
self, request: Any, queryset: QuerySet[Any]
|
|
220
|
+
) -> Optional[QuerySet[Any]]:
|
|
221
|
+
value = self.value()
|
|
222
|
+
if value == "1":
|
|
223
|
+
return queryset.filter(delivered_to=True)
|
|
224
|
+
elif value == "0":
|
|
225
|
+
return queryset.filter(delivered_to=None)
|
|
226
|
+
else:
|
|
227
|
+
return queryset
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
@admin.register(models.BrokerMessage)
|
|
231
|
+
class BrokerMessageAdmin(GuardedModelAdmin):
|
|
232
|
+
"""An admin for a broker message"""
|
|
233
|
+
|
|
234
|
+
search_fields = [
|
|
235
|
+
"topic__slug__icontains",
|
|
236
|
+
"topic__responsetopic__is_response_for__slug__icontains",
|
|
237
|
+
"user__username__icontains",
|
|
238
|
+
"user__email__icontains",
|
|
239
|
+
"user__first_name__icontains",
|
|
240
|
+
"user__last_name__icontains",
|
|
241
|
+
]
|
|
242
|
+
|
|
243
|
+
list_display = [
|
|
244
|
+
"message_id",
|
|
245
|
+
"topic",
|
|
246
|
+
"topic_availability",
|
|
247
|
+
"is_response",
|
|
248
|
+
"user",
|
|
249
|
+
"delivered",
|
|
250
|
+
"date_created",
|
|
251
|
+
]
|
|
252
|
+
|
|
253
|
+
list_filter = [
|
|
254
|
+
"date_created",
|
|
255
|
+
IsResponseMessageFilter,
|
|
256
|
+
HasBeenDeliveredFilter,
|
|
257
|
+
]
|
|
258
|
+
|
|
259
|
+
readonly_fields = ["content"]
|
|
260
|
+
|
|
261
|
+
actions = [send_messages, ping_message_topics]
|
|
262
|
+
|
|
263
|
+
@admin.display(boolean=True) # type: ignore
|
|
264
|
+
def delivered(self, obj: models.BrokerMessage) -> bool:
|
|
265
|
+
return obj.delivered_to.exists()
|
|
266
|
+
|
|
267
|
+
@admin.display(boolean=True) # type: ignore
|
|
268
|
+
def is_response(self, obj: models.BrokerMessage) -> bool:
|
|
269
|
+
return obj.is_response
|
|
270
|
+
|
|
271
|
+
@admin.display(boolean=True, description="Topic online?")
|
|
272
|
+
def topic_availability(self, obj: models.BrokerMessage) -> Optional[bool]:
|
|
273
|
+
return obj.topic.availability
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2022-2025 Helmholtz-Zentrum hereon GmbH
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: EUPL-1.2
|
|
4
|
+
|
|
5
|
+
"""App settings
|
|
6
|
+
------------
|
|
7
|
+
|
|
8
|
+
This module defines the settings options for the
|
|
9
|
+
``dasf-broker-django`` app.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
from enum import Enum
|
|
15
|
+
from typing import Optional
|
|
16
|
+
|
|
17
|
+
from django.conf import settings # noqa: F401
|
|
18
|
+
|
|
19
|
+
#: Create new topics on message
|
|
20
|
+
#:
|
|
21
|
+
#: This flag controls if new topics are created when a message comes from a
|
|
22
|
+
#: producer. If False, messages with non-existing topics are ignored.
|
|
23
|
+
#:
|
|
24
|
+
#: Note that a user also needs the `dasf_broker.add_BrokerTopic`
|
|
25
|
+
#: permission to create topics.
|
|
26
|
+
DASF_CREATE_TOPIC_ON_MESSAGE: bool = getattr(
|
|
27
|
+
settings, "DASF_CREATE_TOPIC_ON_MESSAGE", True
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class StoreMessageOptions(str, Enum):
|
|
32
|
+
DISABLED = "disabled"
|
|
33
|
+
CACHE = "cache"
|
|
34
|
+
CACHEALL = "cacheall"
|
|
35
|
+
STORE = "store"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
#: Shall the messages be stored?
|
|
39
|
+
#:
|
|
40
|
+
#: This flag controls whether the message broker caches messages from producers
|
|
41
|
+
#: until they are consumed by the consumer. This is useful if the consumer
|
|
42
|
+
#: looses connection to the server. This settings can take three different
|
|
43
|
+
#: values:
|
|
44
|
+
#:
|
|
45
|
+
#: ``"disabled"``
|
|
46
|
+
#: The message is not stored at all
|
|
47
|
+
#: ``"cache"``
|
|
48
|
+
#: The message is stored and removed ones one of the potential `consumers`
|
|
49
|
+
#: acknowledges the message
|
|
50
|
+
#: ``"cacheall"``
|
|
51
|
+
#: The message is stored and removed ones **all** `consumers` acknowledged
|
|
52
|
+
#: the message
|
|
53
|
+
#: ``"store"``
|
|
54
|
+
#: The message and response topics are stored forever and are not
|
|
55
|
+
#: automatically removed
|
|
56
|
+
#:
|
|
57
|
+
#: See Also
|
|
58
|
+
#: --------
|
|
59
|
+
#: DASF_STORE_SOURCE_MESSAGES
|
|
60
|
+
#: DASF_STORE_RESPONSE_MESSAGES
|
|
61
|
+
DASF_STORE_MESSAGES: StoreMessageOptions = StoreMessageOptions(
|
|
62
|
+
getattr(settings, "DASF_STORE_MESSAGES", StoreMessageOptions.CACHE)
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
#: Shall the source messages be stored?
|
|
66
|
+
#:
|
|
67
|
+
#: This flag controls whether the message broker caches messages from producers
|
|
68
|
+
#: to topics that are **not** marked as response topic. If this setting is not
|
|
69
|
+
#: set, we use the ``DASF_STORE_MESSAGES`` setting.
|
|
70
|
+
DASF_STORE_SOURCE_MESSAGES: StoreMessageOptions = StoreMessageOptions(
|
|
71
|
+
getattr(settings, "DASF_STORE_SOURCE_MESSAGES", DASF_STORE_MESSAGES)
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
#: Shall the messages to response topics be stored?
|
|
75
|
+
#:
|
|
76
|
+
#: This flag controls whether the message broker caches messages from producers
|
|
77
|
+
#: to topics that are marked as response topic. If this setting is not set, we
|
|
78
|
+
#: use the ``DASF_STORE_MESSAGES`` setting.
|
|
79
|
+
DASF_STORE_RESPONSE_MESSAGES: StoreMessageOptions = StoreMessageOptions(
|
|
80
|
+
getattr(settings, "DASF_STORE_RESPONSE_MESSAGES", DASF_STORE_MESSAGES)
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
#: URL route for the websocket
|
|
84
|
+
#:
|
|
85
|
+
#: This setting controls, where we expect to find the websockets.
|
|
86
|
+
#: As there is no analog to :func:`django.urls.reverse` for channels, you
|
|
87
|
+
#: should use this setting in your ``asgi.py`` file to include the routes
|
|
88
|
+
#: of this package.
|
|
89
|
+
#:
|
|
90
|
+
#: Examples
|
|
91
|
+
#: --------
|
|
92
|
+
#: In your ``asgi.py`` file, include it like:
|
|
93
|
+
#:
|
|
94
|
+
#: .. code-block:: python
|
|
95
|
+
#:
|
|
96
|
+
#: from channels.routing import ProtocolTypeRouter, URLRouter
|
|
97
|
+
#: from django.core.asgi import get_asgi_application
|
|
98
|
+
#: from channels.auth import AuthMiddlewareStack
|
|
99
|
+
#: import dasf_broker.routing as dasf_routing
|
|
100
|
+
#: from dasf_broker.app_settings import DASF_WEBSOCKET_URL_ROUTE
|
|
101
|
+
#:
|
|
102
|
+
#: application = ProtocolTypeRouter(
|
|
103
|
+
#: {
|
|
104
|
+
#: "http": get_asgi_application(),
|
|
105
|
+
#: "websocket": AuthMiddlewareStack(
|
|
106
|
+
#: URLRouter(
|
|
107
|
+
#: [
|
|
108
|
+
#: path(
|
|
109
|
+
#: DASF_WEBSOCKET_URL_ROUTE,
|
|
110
|
+
#: URLRouter(dasf_routing.websocket_urlpatterns),
|
|
111
|
+
#: )
|
|
112
|
+
#: ]
|
|
113
|
+
#: )
|
|
114
|
+
#: ),
|
|
115
|
+
#: }
|
|
116
|
+
#: )
|
|
117
|
+
DASF_WEBSOCKET_URL_ROUTE: str = getattr(
|
|
118
|
+
settings, "DASF_WEBSOCKET_URL_ROUTE", "ws/"
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
#: root URL to your application
|
|
123
|
+
#:
|
|
124
|
+
#: You can use this setting if you are behind a reverse proxy and the
|
|
125
|
+
#: host names, etc. are not handled correctly.
|
|
126
|
+
#:
|
|
127
|
+
#: If you leave this empty, we will use the ``build_absolute_uri`` method
|
|
128
|
+
#: of the http request.
|
|
129
|
+
#:
|
|
130
|
+
#: Examples
|
|
131
|
+
#: --------
|
|
132
|
+
#: A standard value for this would be ``http://localhost:8000``
|
|
133
|
+
ROOT_URL: Optional[str] = None
|
dasf_broker/apps.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2022-2025 Helmholtz-Zentrum hereon GmbH
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: EUPL-1.2
|
|
4
|
+
|
|
5
|
+
"""App config
|
|
6
|
+
----------
|
|
7
|
+
|
|
8
|
+
App config for the dasf_broker app.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from django.apps import AppConfig
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class DjangoHelmholtzAaiConfig(AppConfig):
|
|
15
|
+
default_auto_field = "django.db.models.BigAutoField"
|
|
16
|
+
name = "dasf_broker"
|
dasf_broker/constants.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2022-2025 Helmholtz-Zentrum hereon GmbH
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: EUPL-1.2
|
|
4
|
+
|
|
5
|
+
"""Constants within the DASF Framework
|
|
6
|
+
-----------------------------------
|
|
7
|
+
|
|
8
|
+
Constants from :mod:`demessaging.PulsarMessageConstants`.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from enum import Enum
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class PropertyKeys(str, Enum):
|
|
15
|
+
REQUEST_CONTEXT = "requestContext"
|
|
16
|
+
RESPONSE_TOPIC = "response_topic"
|
|
17
|
+
REQUEST_MESSAGEID = "requestMessageId"
|
|
18
|
+
MESSAGE_TYPE = "messageType"
|
|
19
|
+
FRAGMENT = "fragment"
|
|
20
|
+
NUM_FRAGMENTS = "num_fragments"
|
|
21
|
+
STATUS = "status"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class MessageType(str, Enum):
|
|
25
|
+
PING = "ping"
|
|
26
|
+
PONG = "pong"
|
|
27
|
+
REQUEST = "request"
|
|
28
|
+
RESPONSE = "response"
|
|
29
|
+
LOG = "log"
|
|
30
|
+
INFO = "info"
|
|
31
|
+
PROGRESS = "progress"
|