sovereign 1.0.0b101__tar.gz → 1.0.0b102__tar.gz
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.
Potentially problematic release.
This version of sovereign might be problematic. Click here for more details.
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/PKG-INFO +1 -1
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/pyproject.toml +1 -1
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/context.py +1 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/schemas.py +2 -1
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/sources/poller.py +90 -5
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/templates/resources.html +7 -1
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/views/api.py +24 -1
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/views/interface.py +2 -16
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/worker.py +23 -37
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/LICENSE.txt +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/README.md +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/__init__.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/app.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/cache.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/constants.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/dynamic_config/__init__.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/dynamic_config/deser.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/dynamic_config/loaders.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/error_info.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/logging/access_logger.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/logging/application_logger.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/logging/base_logger.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/logging/bootstrapper.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/logging/types.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/middlewares.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/modifiers/__init__.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/modifiers/lib.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/rendering.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/response_class.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/server.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/sources/__init__.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/sources/file.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/sources/inline.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/sources/lib.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/static/node_expression.js +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/static/panel.js +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/static/sass/style.scss +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/static/style.css +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/statistics.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/templates/base.html +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/templates/err.html +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/testing/loaders.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/testing/modifiers.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/tracing.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/utils/__init__.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/utils/auth.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/utils/crypto/__init__.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/utils/crypto/crypto.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/utils/crypto/suites/__init__.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/utils/crypto/suites/aes_gcm_cipher.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/utils/crypto/suites/base_cipher.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/utils/crypto/suites/disabled_cipher.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/utils/crypto/suites/fernet_cipher.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/utils/dictupdate.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/utils/eds.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/utils/entry_point_loader.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/utils/mock.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/utils/resources.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/utils/templates.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/utils/timer.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/utils/version_info.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/utils/weighted_clusters.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/views/__init__.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/views/crypto.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/views/discovery.py +0 -0
- {sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/views/healthchecks.py +0 -0
|
@@ -410,7 +410,7 @@ class DiscoveryRequest(BaseModel):
|
|
|
410
410
|
return f"version={self.envoy_version}, cluster={self.node.cluster}, resource={self.resource_type}, names={self.resources}"
|
|
411
411
|
|
|
412
412
|
def __str__(self) -> str:
|
|
413
|
-
return f"
|
|
413
|
+
return f"DiscoveryRequest({self.debug()})"
|
|
414
414
|
|
|
415
415
|
|
|
416
416
|
class DiscoveryResponse(BaseModel):
|
|
@@ -645,6 +645,7 @@ class AccessLogConfiguration(BaseSettings):
|
|
|
645
645
|
class LoggingConfiguration(BaseSettings):
|
|
646
646
|
application_logs: ApplicationLogConfiguration = ApplicationLogConfiguration()
|
|
647
647
|
access_logs: AccessLogConfiguration = AccessLogConfiguration()
|
|
648
|
+
log_source_diffs: bool = False
|
|
648
649
|
|
|
649
650
|
|
|
650
651
|
class ContextFileCache(BaseSettings):
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import json
|
|
1
2
|
import asyncio
|
|
2
3
|
import traceback
|
|
3
4
|
from copy import deepcopy
|
|
@@ -7,11 +8,7 @@ from typing import Iterable, Any, Dict, List, Union, Type, Optional
|
|
|
7
8
|
|
|
8
9
|
from glom import glom, PathAccessError
|
|
9
10
|
|
|
10
|
-
from sovereign.schemas import
|
|
11
|
-
ConfiguredSource,
|
|
12
|
-
SourceData,
|
|
13
|
-
Node,
|
|
14
|
-
)
|
|
11
|
+
from sovereign.schemas import ConfiguredSource, SourceData, Node, config
|
|
15
12
|
from sovereign.utils.entry_point_loader import EntryPointLoader
|
|
16
13
|
from sovereign.sources.lib import Source
|
|
17
14
|
from sovereign.modifiers.lib import Modifier, GlobalModifier
|
|
@@ -36,6 +33,78 @@ Mods = Dict[str, Type[Modifier]]
|
|
|
36
33
|
GMods = Dict[str, Type[GlobalModifier]]
|
|
37
34
|
|
|
38
35
|
|
|
36
|
+
def item_comparison(old, new):
|
|
37
|
+
if not isinstance(old, dict) or not isinstance(new, dict):
|
|
38
|
+
return ["content_changed"]
|
|
39
|
+
|
|
40
|
+
changes = []
|
|
41
|
+
all_keys = set(old.keys()) | set(new.keys())
|
|
42
|
+
|
|
43
|
+
for key in sorted(all_keys):
|
|
44
|
+
old_val = old.get(key)
|
|
45
|
+
new_val = new.get(key)
|
|
46
|
+
|
|
47
|
+
if old_val != new_val:
|
|
48
|
+
if key not in old:
|
|
49
|
+
changes.append(f"+{key}:{new_val}")
|
|
50
|
+
elif key not in new:
|
|
51
|
+
changes.append(f"-{key}:{old_val}")
|
|
52
|
+
else:
|
|
53
|
+
changes.append(f"~{key}:{old_val}→{new_val}")
|
|
54
|
+
|
|
55
|
+
return changes
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def per_field_diff(old, new):
|
|
59
|
+
changes = []
|
|
60
|
+
max_len = max(len(old), len(new))
|
|
61
|
+
|
|
62
|
+
for i in range(max_len):
|
|
63
|
+
old_inst = old[i] if i < len(old) else None
|
|
64
|
+
new_inst = new[i] if i < len(new) else None
|
|
65
|
+
|
|
66
|
+
if old_inst is None:
|
|
67
|
+
changes.append(f"added [index:{i}] {new_inst}")
|
|
68
|
+
elif new_inst is None:
|
|
69
|
+
changes.append(f"removed [index:{i}] {old_inst}")
|
|
70
|
+
elif old_inst != new_inst:
|
|
71
|
+
field_changes = item_comparison(old_inst, new_inst)
|
|
72
|
+
if field_changes:
|
|
73
|
+
changes.append(f"modified [index:{i}]: {', '.join(field_changes)}")
|
|
74
|
+
|
|
75
|
+
return changes
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def source_diff_summary(prev, curr):
|
|
79
|
+
if prev is None:
|
|
80
|
+
return [
|
|
81
|
+
f"scope:{scope} added:{len(instances)} instances"
|
|
82
|
+
for scope, instances in curr.scopes.items()
|
|
83
|
+
if instances
|
|
84
|
+
]
|
|
85
|
+
|
|
86
|
+
summary = []
|
|
87
|
+
all_scopes = set(prev.scopes.keys()) | set(curr.scopes.keys())
|
|
88
|
+
|
|
89
|
+
for scope in sorted(all_scopes):
|
|
90
|
+
old = prev.scopes.get(scope, [])
|
|
91
|
+
new = curr.scopes.get(scope, [])
|
|
92
|
+
|
|
93
|
+
n_old = len(old)
|
|
94
|
+
n_new = len(new)
|
|
95
|
+
|
|
96
|
+
if n_old == 0 and n_new > 0:
|
|
97
|
+
summary.append(f"scope:{scope} added:{n_new} instances")
|
|
98
|
+
elif n_old > 0 and n_new == 0:
|
|
99
|
+
summary.append(f"scope:{scope} removed:{n_old} instances")
|
|
100
|
+
elif old != new:
|
|
101
|
+
detailed_changes = per_field_diff(old, new)
|
|
102
|
+
if detailed_changes:
|
|
103
|
+
summary.append(f"scope:{scope} changes: {'; '.join(detailed_changes)}")
|
|
104
|
+
|
|
105
|
+
return summary if summary else ["no changes detected"]
|
|
106
|
+
|
|
107
|
+
|
|
39
108
|
class SourcePoller:
|
|
40
109
|
def __init__(
|
|
41
110
|
self,
|
|
@@ -179,9 +248,25 @@ class SourcePoller:
|
|
|
179
248
|
else:
|
|
180
249
|
self.stats.increment("sources.refreshed")
|
|
181
250
|
self.last_updated = datetime.now()
|
|
251
|
+
old_data = getattr(self, "source_data", None)
|
|
182
252
|
self.instance_count = len(
|
|
183
253
|
[instance for scope in new.scopes.values() for instance in scope]
|
|
184
254
|
)
|
|
255
|
+
|
|
256
|
+
if config.logging.log_source_diffs:
|
|
257
|
+
diff_summary = source_diff_summary(old_data, new)
|
|
258
|
+
# printing json directly because the logger is fucking stupid
|
|
259
|
+
print(
|
|
260
|
+
json.dumps(
|
|
261
|
+
dict(
|
|
262
|
+
event="Sources refreshed with changes",
|
|
263
|
+
level="info",
|
|
264
|
+
diff=diff_summary,
|
|
265
|
+
total_instances=self.instance_count,
|
|
266
|
+
)
|
|
267
|
+
)
|
|
268
|
+
)
|
|
269
|
+
|
|
185
270
|
self.source_data = new
|
|
186
271
|
return True
|
|
187
272
|
|
|
@@ -14,6 +14,12 @@
|
|
|
14
14
|
];
|
|
15
15
|
const resources = resourceNames.map((name, index) => ({ name: name, index: index }));
|
|
16
16
|
let filteredResources = [...resources];
|
|
17
|
+
|
|
18
|
+
// Function to set envoy_version cookie and reload page
|
|
19
|
+
function setEnvoyVersion(version) {
|
|
20
|
+
document.cookie = `envoy_version=${version}; path=/ui/resources/; max-age=31536000`;
|
|
21
|
+
window.location.reload();
|
|
22
|
+
}
|
|
17
23
|
</script>
|
|
18
24
|
<style>
|
|
19
25
|
#filterInput {
|
|
@@ -284,7 +290,7 @@
|
|
|
284
290
|
</div>
|
|
285
291
|
{% for v in available_versions %}
|
|
286
292
|
<a class="dropdown-item{% if v == version %} is-active{% endif %}"
|
|
287
|
-
href="
|
|
293
|
+
href="#" onclick="setEnvoyVersion('{{ v }}'); return false;">
|
|
288
294
|
{{ v.replace('_', '') }}
|
|
289
295
|
</a>
|
|
290
296
|
{% endfor %}
|
|
@@ -11,6 +11,20 @@ from sovereign.utils.mock import mock_discovery_request
|
|
|
11
11
|
router = APIRouter()
|
|
12
12
|
|
|
13
13
|
|
|
14
|
+
def _traverse(data, prefix, expressions):
|
|
15
|
+
for key, value in data.items():
|
|
16
|
+
path = f"{prefix}.{key}" if prefix else key
|
|
17
|
+
if isinstance(value, dict):
|
|
18
|
+
yield from _traverse(value, path, expressions)
|
|
19
|
+
else:
|
|
20
|
+
yield f"{path}={value}"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def expand_metadata_to_expr(m):
|
|
24
|
+
exprs = []
|
|
25
|
+
yield from _traverse(m, "", exprs)
|
|
26
|
+
|
|
27
|
+
|
|
14
28
|
@router.get("/resources/{resource_type}", summary="Get resources for a given type")
|
|
15
29
|
async def resource(
|
|
16
30
|
resource_type: DiscoveryTypes = Path(title="xDS Resource type"),
|
|
@@ -19,16 +33,25 @@ async def resource(
|
|
|
19
33
|
service_cluster: Optional[str] = Query("*", title="Envoy Service cluster"),
|
|
20
34
|
region: Optional[str] = Query(None, title="Locality Zone"),
|
|
21
35
|
version: Optional[str] = Query(None, title="Envoy Semantic Version"),
|
|
36
|
+
metadata: Optional[str] = Query(None, title="Envoy node metadata to filter by"),
|
|
22
37
|
) -> Response:
|
|
38
|
+
expressions = [f"cluster={service_cluster}"]
|
|
39
|
+
try:
|
|
40
|
+
metadata = json.loads(metadata or "{}")
|
|
41
|
+
for expr in expand_metadata_to_expr(metadata):
|
|
42
|
+
expressions.append(expr)
|
|
43
|
+
except Exception:
|
|
44
|
+
pass
|
|
23
45
|
kwargs = dict(
|
|
24
46
|
api_version=api_version,
|
|
25
47
|
resource_type=DiscoveryTypes(resource_type).value,
|
|
26
48
|
resource_names=resource_name,
|
|
27
49
|
version=version,
|
|
28
50
|
region=region,
|
|
29
|
-
expressions=
|
|
51
|
+
expressions=expressions,
|
|
30
52
|
)
|
|
31
53
|
req = mock_discovery_request(**{k: v for k, v in kwargs.items() if v is not None})
|
|
54
|
+
print(req)
|
|
32
55
|
response = await cache.blocking_read(req)
|
|
33
56
|
if content := getattr(response, "text", None):
|
|
34
57
|
return Response(content, media_type="application/json")
|
|
@@ -5,7 +5,7 @@ from typing import Any, Dict, List
|
|
|
5
5
|
from fastapi import APIRouter, Cookie, Path, Query
|
|
6
6
|
from fastapi.encoders import jsonable_encoder
|
|
7
7
|
from fastapi.requests import Request
|
|
8
|
-
from fastapi.responses import HTMLResponse, JSONResponse,
|
|
8
|
+
from fastapi.responses import HTMLResponse, JSONResponse, Response
|
|
9
9
|
|
|
10
10
|
from sovereign import html_templates, cache
|
|
11
11
|
from sovereign.schemas import DiscoveryTypes, XDS_TEMPLATES
|
|
@@ -18,6 +18,7 @@ all_types = [t.value for t in DiscoveryTypes]
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
@router.get("/")
|
|
21
|
+
@router.get("/resources")
|
|
21
22
|
async def ui_main(request: Request) -> HTMLResponse:
|
|
22
23
|
try:
|
|
23
24
|
return html_templates.TemplateResponse(
|
|
@@ -42,21 +43,6 @@ async def ui_main(request: Request) -> HTMLResponse:
|
|
|
42
43
|
)
|
|
43
44
|
|
|
44
45
|
|
|
45
|
-
@router.get(
|
|
46
|
-
"/set-version", summary="Filter the UI by a certain Envoy Version (stores a Cookie)"
|
|
47
|
-
)
|
|
48
|
-
async def set_envoy_version(
|
|
49
|
-
request: Request,
|
|
50
|
-
version: str = Query(
|
|
51
|
-
"__any__", title="The clients envoy version to emulate in this XDS request"
|
|
52
|
-
),
|
|
53
|
-
) -> Response:
|
|
54
|
-
url = request.headers.get("Referer", "/ui")
|
|
55
|
-
response = RedirectResponse(url=url)
|
|
56
|
-
response.set_cookie(key="envoy_version", value=version)
|
|
57
|
-
return response
|
|
58
|
-
|
|
59
|
-
|
|
60
46
|
@router.get(
|
|
61
47
|
"/resources/{xds_type}", summary="List available resources for a given xDS type"
|
|
62
48
|
)
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
from typing import Optional
|
|
3
|
-
from multiprocessing import Process
|
|
3
|
+
from multiprocessing import Process, cpu_count
|
|
4
4
|
from contextlib import asynccontextmanager
|
|
5
|
-
from concurrent.futures import ThreadPoolExecutor
|
|
6
5
|
|
|
7
6
|
from fastapi import FastAPI, Body
|
|
8
7
|
|
|
@@ -23,10 +22,9 @@ from sovereign.context import NEW_CONTEXT
|
|
|
23
22
|
|
|
24
23
|
ClientId = str
|
|
25
24
|
ONDEMAND: asyncio.Queue[tuple[ClientId, DiscoveryRequest]] = asyncio.Queue(100)
|
|
26
|
-
|
|
25
|
+
RENDER_SEMAPHORE = asyncio.Semaphore(cpu_count())
|
|
27
26
|
|
|
28
27
|
|
|
29
|
-
# TODO: do something about this ---------------------------------------
|
|
30
28
|
def hidden_field(*args, **kwargs):
|
|
31
29
|
return "(value hidden)"
|
|
32
30
|
|
|
@@ -62,43 +60,37 @@ if config.sources is not None:
|
|
|
62
60
|
context_middleware.append(poller.add_to_context)
|
|
63
61
|
|
|
64
62
|
|
|
65
|
-
if poller is not None:
|
|
66
|
-
poller.lazy_load_modifiers(config.modifiers)
|
|
67
|
-
poller.lazy_load_global_modifiers(config.global_modifiers)
|
|
68
|
-
|
|
69
|
-
template_context.middleware = context_middleware
|
|
70
|
-
# ---------------------------------------------------------------------
|
|
71
|
-
|
|
72
|
-
|
|
73
63
|
def render(job: rendering.RenderJob):
|
|
74
64
|
log.debug(f"Spawning render process for {job.id}")
|
|
75
65
|
Process(target=rendering.generate, args=[job]).start()
|
|
76
66
|
|
|
77
67
|
|
|
78
|
-
def
|
|
79
|
-
|
|
80
|
-
|
|
68
|
+
async def submit_render(job: rendering.RenderJob):
|
|
69
|
+
async with RENDER_SEMAPHORE:
|
|
70
|
+
render(job)
|
|
81
71
|
|
|
82
72
|
|
|
83
73
|
async def render_on_event():
|
|
84
74
|
while True:
|
|
85
75
|
# block forever until new context arrives
|
|
86
76
|
await NEW_CONTEXT.wait()
|
|
87
|
-
stats.increment("template.render_on_event")
|
|
88
77
|
log.debug("New context detected, re-rendering templates")
|
|
89
78
|
try:
|
|
90
79
|
if registered := cache.clients():
|
|
91
80
|
log.debug("New context detected, re-rendering templates")
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
)
|
|
81
|
+
jobs = [
|
|
82
|
+
rendering.RenderJob(
|
|
83
|
+
id=client,
|
|
84
|
+
request=request,
|
|
85
|
+
context=template_context.get_context(request),
|
|
86
|
+
)
|
|
87
|
+
for client, request in registered
|
|
88
|
+
]
|
|
89
|
+
tasks = [submit_render(job) for job in jobs]
|
|
90
|
+
size = len(tasks)
|
|
91
|
+
stats.increment("template.render_on_event", tags=[f"batch_size:{size}"])
|
|
92
|
+
await asyncio.gather(*tasks)
|
|
93
|
+
log.debug(f"Completed rendering {size} jobs")
|
|
102
94
|
finally:
|
|
103
95
|
NEW_CONTEXT.clear()
|
|
104
96
|
|
|
@@ -111,7 +103,7 @@ async def render_on_demand():
|
|
|
111
103
|
job = rendering.RenderJob(
|
|
112
104
|
id=id, request=request, context=template_context.get_context(request)
|
|
113
105
|
)
|
|
114
|
-
await
|
|
106
|
+
await submit_render(job)
|
|
115
107
|
ONDEMAND.task_done()
|
|
116
108
|
|
|
117
109
|
|
|
@@ -124,25 +116,19 @@ async def lifespan(_: FastAPI):
|
|
|
124
116
|
|
|
125
117
|
# Template context
|
|
126
118
|
log.debug("Starting context loop")
|
|
119
|
+
template_context.middleware = context_middleware
|
|
127
120
|
asyncio.create_task(template_context.start())
|
|
128
121
|
await NEW_CONTEXT.wait() # first refresh finished
|
|
129
122
|
|
|
130
123
|
# Source polling
|
|
131
124
|
if poller is not None:
|
|
132
125
|
log.debug("Starting source poller")
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
126
|
+
poller.lazy_load_modifiers(config.modifiers)
|
|
127
|
+
poller.lazy_load_global_modifiers(config.global_modifiers)
|
|
128
|
+
asyncio.create_task(poller.poll_forever())
|
|
136
129
|
yield
|
|
137
130
|
|
|
138
131
|
|
|
139
|
-
def poller_thread(poller):
|
|
140
|
-
log.debug("Starting source poller")
|
|
141
|
-
loop = asyncio.new_event_loop()
|
|
142
|
-
asyncio.set_event_loop(loop)
|
|
143
|
-
loop.run_until_complete(poller.poll_forever())
|
|
144
|
-
|
|
145
|
-
|
|
146
132
|
worker = FastAPI(lifespan=lifespan)
|
|
147
133
|
try:
|
|
148
134
|
import sentry_sdk
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/utils/crypto/suites/aes_gcm_cipher.py
RENAMED
|
File without changes
|
{sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/utils/crypto/suites/base_cipher.py
RENAMED
|
File without changes
|
{sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/utils/crypto/suites/disabled_cipher.py
RENAMED
|
File without changes
|
{sovereign-1.0.0b101 → sovereign-1.0.0b102}/src/sovereign/utils/crypto/suites/fernet_cipher.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|