Coverage for src/lumen/cortex/internal_plugins/analytics/plugin.py: 0%
41 statements
« prev ^ index » next coverage.py v7.16.0, created at 2026-08-31 18:46 +0000
« prev ^ index » next coverage.py v7.16.0, created at 2026-08-31 18:46 +0000
1"""
2AnalyticsPlugin — Built-in system plugin for high-performance analytics.
4Exposes custom FHIR operations over HTTP:
5- Observation/$search-pandas: Returns a flat JSON list of normalised records.
6- Observation/$search-duckdb: Executes a SQL query in-process using DuckDB.
7"""
9from __future__ import annotations
11import json
12from typing import Any
14import lumen.analytics.in_process as analytics
16from ...context import PluginContext
17from ...operation import OperationInvocation
18from ...plugin import Plugin, operation
21class AnalyticsPlugin(Plugin):
22 name = "analytics-plugin"
23 version = "1.0.0"
24 requires_cortex = "1.0"
26 @operation("search-pandas", on="Observation", scope="type", timeout_ms=30_000)
27 async def search_pandas(
28 self, ctx: PluginContext, op: OperationInvocation
29 ) -> list[dict[str, Any]]:
30 """FHIR Operation: Observation/$search-pandas
32 Fetches matching resources in-process and returns a flat JSON record list.
33 """
34 df = await analytics.search_pandas("Observation", params=op.query)
35 if df.empty:
36 return []
37 return df.to_dict(orient="records")
39 @operation("search-duckdb", on="Observation", scope="type", timeout_ms=30_000)
40 async def search_duckdb(
41 self, ctx: PluginContext, op: OperationInvocation
42 ) -> list[dict[str, Any]]:
43 """FHIR Operation: Observation/$search-duckdb
45 Executes a DuckDB SQL query on the server-side DataFrame.
46 """
47 import duckdb
49 body = op.body or {}
50 if isinstance(body, bytes):
51 try:
52 body = json.loads(body.decode("utf-8"))
53 except Exception:
54 body = {}
56 sql_query = body.get("query")
57 if not sql_query:
58 return [{"error": "Missing 'query' parameter in request body"}]
60 fhir_params = body.get("params", {})
62 # Load data in-process as a Pandas DataFrame
63 df = await analytics.search_pandas("Observation", params=fhir_params)
64 if df.empty:
65 return []
67 # Run DuckDB SQL query in-process on the DataFrame
68 try:
69 conn = duckdb.connect()
70 conn.register("df", df)
71 conn.register("Observation", df)
72 result_df = conn.execute(sql_query).df()
73 except Exception as e:
74 return [{"error": f"DuckDB SQL query failed: {e!s}"}]
76 return result_df.to_dict(orient="records")