Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .github/workflows/apply-httproute.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: apply-httproute

on:
workflow_dispatch:

jobs:
httproute:
name: apply httproute
runs-on: ubuntu-latest
permissions:
contents: read

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Configure kubeconfig
env:
KUBECONFIG_B64: ${{ secrets.KUBECONFIG_B64 }}
run: |
mkdir -p ~/.kube
echo "${KUBECONFIG_B64}" | base64 -d > ~/.kube/config

- name: Apply HTTPRoute
run: |
set -euo pipefail
kubectl apply --dry-run=server -f deployment/httproute.yaml -n website
kubectl apply -f deployment/httproute.yaml -n website

- name: Wait for route to be accepted
run: |
set -euo pipefail
for route in docs docs-redirect; do
for cond in Accepted ResolvedRefs; do
kubectl wait --timeout=60s -n website "httproute/$route" \
--for=jsonpath="{.status.parents[0].conditions[?(@.type==\"$cond\")].status}"=True
done
done
35 changes: 0 additions & 35 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -130,38 +130,3 @@ jobs:
--default-repo=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} \
--build-artifacts build.out.json \
-m ${{ env.MODULE }}

httproute:
name: apply httproute
needs: deploy
if: github.event_name != 'pull_request'
runs-on: ubuntu-latest
permissions:
contents: read

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Configure kubeconfig
env:
KUBECONFIG_B64: ${{ secrets.KUBECONFIG_B64 }}
run: |
mkdir -p ~/.kube
echo "${KUBECONFIG_B64}" | base64 -d > ~/.kube/config

- name: Apply HTTPRoute
run: |
set -euo pipefail
kubectl apply --dry-run=server -f deployment/httproute.yaml -n website
kubectl apply -f deployment/httproute.yaml -n website

- name: Wait for route to be accepted
run: |
set -euo pipefail
for route in docs docs-redirect; do
for cond in Accepted ResolvedRefs; do
kubectl wait --timeout=60s -n website "httproute/$route" \
--for=jsonpath="{.status.parents[0].conditions[?(@.type==\"$cond\")].status}"=True
done
done
22 changes: 20 additions & 2 deletions docs/UML/drawio/hexagonal-architecture.drawio
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<mxfile host="Electron" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/29.3.0 Chrome/140.0.7339.249 Electron/38.7.2 Safari/537.36" version="29.3.0">
<diagram name="Page-1" id="DFCrOaSrRtZvU-2D4lRB">
<mxGraphModel dx="1072" dy="647" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<mxGraphModel dx="1554" dy="938" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="IdZxaUeP-qgIX7MlmHNZ-1" parent="1" style="shape=hexagon;perimeter=hexagonPerimeter2;whiteSpace=wrap;html=1;fixedSize=1;strokeWidth=2;" value="&lt;font style=&quot;font-size: 18px;&quot; face=&quot;Lucida Console&quot;&gt;hololinked.core&lt;/font&gt;&lt;div&gt;&lt;br&gt;&lt;div&gt;Thing&lt;/div&gt;&lt;div&gt;Property, Action, Event&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;background-color: transparent; color: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&gt;RPCServer, EventPublisher&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;" vertex="1">
<mxCell id="IdZxaUeP-qgIX7MlmHNZ-1" parent="1" style="shape=hexagon;perimeter=hexagonPerimeter2;whiteSpace=wrap;html=1;fixedSize=1;strokeWidth=2;" value="&lt;font style=&quot;font-size: 18px;&quot; face=&quot;Lucida Console&quot;&gt;&lt;b&gt;hololinked.core&lt;/b&gt;&lt;/font&gt;&lt;div&gt;&lt;br&gt;&lt;div&gt;Thing&lt;/div&gt;&lt;div&gt;Property, Action, Event&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;background-color: transparent; color: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&gt;EventLoop, EventPublisher&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;" vertex="1">
<mxGeometry height="110" width="200" x="310" y="440" as="geometry" />
</mxCell>
<mxCell id="IdZxaUeP-qgIX7MlmHNZ-3" edge="1" parent="1" style="endArrow=none;html=1;rounded=0;" value="">
Expand Down Expand Up @@ -118,6 +118,24 @@
<mxCell id="IFCsPYImHeIqqcxwqQ8c-4" parent="1" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=2;" value="Payload Validators&lt;div&gt;(Schema based)&lt;/div&gt;" vertex="1">
<mxGeometry height="50" width="120" x="670.0000000000001" y="660" as="geometry" />
</mxCell>
<mxCell id="4ZsR0iUJvaOZTn2S6U-_-1" parent="1" style="text;html=1;whiteSpace=wrap;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;rounded=0;" value="&lt;b&gt;&lt;font style=&quot;color: rgb(255, 23, 21); font-size: 9px;&quot;&gt;BaseSchemaValidator&lt;/font&gt;&lt;/b&gt;&lt;div&gt;&lt;b&gt;&lt;font style=&quot;color: rgb(255, 23, 21); font-size: 9px;&quot;&gt;interface&lt;/font&gt;&lt;/b&gt;&lt;/div&gt;" vertex="1">
<mxGeometry height="30" width="140" x="455" y="660" as="geometry" />
</mxCell>
<mxCell id="4ZsR0iUJvaOZTn2S6U-_-2" parent="1" style="text;html=1;whiteSpace=wrap;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;rounded=0;" value="&lt;b&gt;&lt;font style=&quot;color: rgb(255, 23, 21); font-size: 9px;&quot;&gt;BaseConfigurationRepository&lt;/font&gt;&lt;/b&gt;&lt;div&gt;&lt;b&gt;&lt;font style=&quot;color: rgb(255, 23, 21); font-size: 9px;&quot;&gt;interface&lt;/font&gt;&lt;/b&gt;&lt;/div&gt;" vertex="1">
<mxGeometry height="30" width="140" x="544" y="556" as="geometry" />
</mxCell>
<mxCell id="4ZsR0iUJvaOZTn2S6U-_-3" parent="1" style="text;html=1;whiteSpace=wrap;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;rounded=0;" value="&lt;b&gt;&lt;font style=&quot;color: rgb(255, 23, 21); font-size: 9px;&quot;&gt;Metadata&lt;/font&gt;&lt;/b&gt;&lt;div&gt;&lt;b&gt;&lt;font style=&quot;color: rgb(255, 23, 21); font-size: 9px;&quot;&gt;interface&lt;/font&gt;&lt;/b&gt;&lt;/div&gt;" vertex="1">
<mxGeometry height="30" width="61" x="544" y="460" as="geometry" />
</mxCell>
<mxCell id="4ZsR0iUJvaOZTn2S6U-_-4" parent="1" style="text;html=1;whiteSpace=wrap;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;rounded=0;" value="&lt;font style=&quot;font-size: 9px;&quot;&gt;&lt;font color=&quot;#ff1715&quot;&gt;&lt;b&gt;BaseSerializer&lt;/b&gt;&lt;/font&gt;&lt;br&gt;&lt;/font&gt;&lt;div&gt;&lt;b&gt;&lt;font style=&quot;color: rgb(255, 23, 21); font-size: 9px;&quot;&gt;interface&lt;/font&gt;&lt;/b&gt;&lt;/div&gt;" vertex="1">
<mxGeometry height="30" width="68" x="580" y="395" as="geometry" />
</mxCell>
<mxCell id="4ZsR0iUJvaOZTn2S6U-_-5" parent="1" style="text;html=1;whiteSpace=wrap;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;rounded=0;" value="&lt;font color=&quot;#ff1715&quot; size=&quot;1&quot;&gt;&lt;b&gt;Request-Reply (EventLoop)&lt;/b&gt;&lt;/font&gt;" vertex="1">
<mxGeometry height="30" width="80" x="170" y="360" as="geometry" />
</mxCell>
<mxCell id="4ZsR0iUJvaOZTn2S6U-_-6" parent="1" style="text;html=1;whiteSpace=wrap;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;rounded=0;" value="&lt;font color=&quot;#ff1715&quot; size=&quot;1&quot;&gt;&lt;b&gt;PubSub&lt;/b&gt;&lt;/font&gt;&lt;div&gt;&lt;font color=&quot;#ff1715&quot; size=&quot;1&quot;&gt;&lt;b&gt;(EventPublisher)&lt;/b&gt;&lt;/font&gt;&lt;/div&gt;" vertex="1">
<mxGeometry height="30" width="80" x="170" y="420.35" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
Expand Down
1 change: 1 addition & 0 deletions docs/api-reference/injection/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
options:
members: []
show_root_heading: false
show_root_toc_entry: false

Each registry below resolves an implementation **by name, on first use**.

Expand Down
14 changes: 10 additions & 4 deletions docs/api-reference/namespaces.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
# Import Namespaces

These are the important namespaces in the repository.

| Namespace | Description |
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `hololinked.core` | Definition of [`Thing`](thing/index.md) class, [`Property`](property/index.md), [`Action`](action/index.md) and [`Event`](events/index.md) classes, [`StateMachine`](state-machine/state-machine.md), [`Logger`](thing/logger.md) & the [`EventLoop`](eventloop/eventloop.md) that executes operations. |
| `hololinked.serializers` | Serializers for different data formats (JSON, MessagePack, etc.) and [`Serializers`](serializers/index.md) singleton. |
| `hololinked.serializers` | Serializers for different data formats (JSON, MessagePack, etc.) |
| `hololinked.server` | Protocol specific server implementations |
| `hololinked.client` | [`ObjectProxy`](clients/object-proxy.md) and protocol specific client implementations, client abstractions and [`ClientFactory`](clients/base.md). |
| `hololinked.param` | Copy of `param` library with implementation specific modifications. |
| `hololinked.client` | [`ObjectProxy`](clients/object-proxy.md), protocol specific client implementations, client abstractions and [`ClientFactory`](clients/base.md). |
| `hololinked.param` | Copy of [`holoviz param`](https://param.holoviz.org/en/docs/latest/index.html) library with implementation specific modifications. |
| `hololinked.storage` | Database clients for data persistence. |
| `hololinked.metadata` | Device description languages a `Thing` can be described in. `hololinked.metadata.td` holds the W3C Web of Things Thing Description/[ThingModel](td/tm.md) parsing and generation. |
| `hololinked.injection` | Dependency injection layer. Holds the lazy adapter registries — `Serializers`, `SchemaValidators`, `StorageBackends` and `MetadataFormats` — that resolve an implementation by name on first use. |
| `hololinked.injection` | Dependency injection layer, holds the lazy adapter registries like `Serializers`, `SchemaValidators`, `StorageBackends` and `MetadataFormats` that resolve an implementation by name on first use. |
| `hololinked.schema_validators` | Validators that check property, action and event payloads against a schema (JSON Schema, fastjsonschema, pydantic). |

A [hexagonal architecture](../design/hexagonal-architecture.md) is followed with `hololinked.core` being the important part of the repository.

<img src="../../assets/hexagonal-architecture.drawio.svg" alt="Hexagonal architecture diagram" style="width: 100%; height: auto;" />
2 changes: 1 addition & 1 deletion docs/api-reference/protocols/http/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
- thing_description_service

Pass these as a plain dictionary to the `config` argument of
[`HTTPServer`](index.md) — not as a `RuntimeConfig` instance:
[`HTTPServer`](index.md), not as a `RuntimeConfig` instance:

```python
HTTPServer(config=dict(cors=True, property_handler=MyPropertyHandler))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
# Headers

::: hololinked.server.zmq.message.RequestHeader

options:
heading_level: 2

::: hololinked.server.zmq.message.ResponseHeader
options:
heading_level: 2

::: hololinked.server.zmq.message.EventHeader

options:
heading_level: 2
5 changes: 1 addition & 4 deletions docs/api-reference/server/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,11 @@
::: hololinked.server
options:
show_root_heading: false
show_root_toc_entry: false
members: false

## Entry points

`run()` and `stop()` knows no protocol in particular — they take already-constructed servers and
drive their lifecycle. Use them when you build servers yourself; `Thing.run(access_points=...)` is
the shorthand that calls `run()`.

::: hololinked.server.run
options:
show_root_heading: true
Expand Down
2 changes: 1 addition & 1 deletion docs/assets/hexagonal-architecture.drawio.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
32 changes: 32 additions & 0 deletions docs/design/eventloop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Event Loop

The main purpose of the [`EventLoop`](../api-reference/eventloop/) is to:

- add scheduling control for the interaction affordances
- decouple protocol handlers from the actual execution of the interaction affordances
- unify execution across multiple protocols
- maintain standardized behaviour irrespective of the protocol, for example, pushing an event must cause both a HTTP and a MQTT client to receive the same event

Three types of scheduling are supported:

- **Synchronous** – the default, blocking until the interaction affordance is completed.
- **Async** – non-blocking and can be scheduled on the current async loop.
- **Threaded** – non-blocking and can be scheduled on a separate thread.

All supported protocols retrieve information from their request object, which is used to create an [`Operation`](../api-reference/eventloop/operation.md). The `EventLoop` is invoked with the `Operation`, which handles the scheduling and execution of the interaction affordance. The response is sent back to the protocol handler, which returns the response to the client:

```mermaid
sequenceDiagram
participant Client
participant ProtocolHandler
participant EventLoop

Client->>ProtocolHandler: Send Request
ProtocolHandler->>EventLoop: Schedule an Operation
EventLoop->>EventLoop: Schedule & Execute Affordance (in its own thread)
EventLoop->>ProtocolHandler: Write Response
ProtocolHandler->>Client: Return Response
Note over EventLoop: --- Parallel Event Flow (Pub/Sub) ---
EventLoop-->>ProtocolHandler: Publish Event (Pub)
ProtocolHandler-->>Client: Forward Event (Pub, protocol specific)
```
Loading
Loading