Skip to content

Commit 6457233

Browse files
authored
add support for OGC API Publish-Subscribe Workflow - Part 1: Core (#2146) (#2220)
* add support for OGC API Publish-Subscribe Workflow - Part 1: Core (#2146) * update docs * update docs * fix API deletion on not found items in backend * fix ref * fix docs * add AsyncAPI support * fix tests * add exception handling * update docs
1 parent 84f4412 commit 6457233

35 files changed

Lines changed: 10967 additions & 37 deletions

.github/workflows/main.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ jobs:
126126
pip3 install -r requirements-provider.txt
127127
pip3 install -r requirements-manager.txt
128128
pip3 install -r requirements-django.txt
129+
pip3 install -r requirements-pubsub.txt
129130
pip3 install .
130131
pip3 install GDAL==`gdal-config --version`
131132
- name: setup test data ⚙️

docker/entrypoint.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ fi
4646
if [[ -z "$PYGEOAPI_OPENAPI" ]]; then
4747
export PYGEOAPI_OPENAPI="${PYGEOAPI_HOME}/local.openapi.yml"
4848
fi
49+
if [[ -z "$PYGEOAPI_ASYNCAPI" ]]; then
50+
export PYGEOAPI_ASYNCAPI="${PYGEOAPI_HOME}/local.asyncapi.yml"
51+
fi
4952

5053
# gunicorn env settings with defaults
5154
SCRIPT_NAME=${SCRIPT_NAME:=/}
@@ -87,6 +90,12 @@ echo "Trying to generate openapi.yml"
8790

8891
echo "openapi.yml generated continue to pygeoapi"
8992

93+
echo "Trying to generate asyncapi.yml"
94+
/venv/bin/pygeoapi asyncapi generate ${PYGEOAPI_CONFIG} --output-file ${PYGEOAPI_ASYNCAPI}
95+
96+
[[ $? -ne 0 ]] && error "asyncapi.yml could not be generated ERROR"
97+
echo "asyncapi.yml generated continue to pygeoapi"
98+
9099
start_gunicorn() {
91100
# SCRIPT_NAME should not have value '/'
92101
[[ "${SCRIPT_NAME}" = '/' ]] && export SCRIPT_NAME="" && echo "make SCRIPT_NAME empty from /"

docs/source/administration.rst

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,6 @@ To generate the OpenAPI document, run the following:
2424
2525
This will dump the OpenAPI document as YAML to your system's ``stdout``. To save to a file on disk, run:
2626

27-
.. code-block:: bash
28-
29-
pygeoapi openapi generate /path/to/my-pygeoapi-config.yml > /path/to/my-pygeoapi-openapi.yml
30-
31-
You can also write to a file explicitly via the ``--output-file`` option:
32-
3327
.. code-block:: bash
3428
3529
pygeoapi openapi generate /path/to/my-pygeoapi-config.yml --output-file /path/to/my-pygeoapi-openapi.yml
@@ -38,7 +32,7 @@ To generate the OpenAPI document as JSON, run:
3832

3933
.. code-block:: bash
4034
41-
pygeoapi openapi generate /path/to/my-pygeoapi-config.yml -f json > /path/to/my-pygeoapi-openapi.json
35+
pygeoapi openapi generate /path/to/my-pygeoapi-config.yml --format json --output-file /path/to/my-pygeoapi-openapi.yml
4236
4337
.. note::
4438
Generate as YAML or JSON? If your OpenAPI YAML definition is slow to render as JSON,
@@ -83,6 +77,11 @@ In UNIX:
8377
# or if OpenAPI JSON
8478
export PYGEOAPI_OPENAPI=/path/to/my-pygeoapi-openapi.json
8579
80+
# if your server supports AsyncAPI and Pub/Sub
81+
export PYGEOAPI_ASYNCAPI=/path/to/my-pygeoapi-asyncapi.yml
82+
# or if AsyncAPI JSON
83+
export PYGEOAPI_ASYNCAPI=/path/to/my-pygeoapi-asyncapi.json
84+
8685
In Windows:
8786

8887
.. code-block:: bat
@@ -92,6 +91,14 @@ In Windows:
9291
# or if OpenAPI JSON
9392
set PYGEOAPI_OPENAPI=/path/to/my-pygeoapi-openapi.json
9493
94+
# if your server supports AsyncAPI and Pub/Sub
95+
set PYGEOAPI_ASYNCAPI=/path/to/my-pygeoapi-asyncapi.yml
96+
# or if AsyncAPI JSON
97+
set PYGEOAPI_ASYNCAPI=/path/to/my-pygeoapi-asyncapi.json
98+
99+
.. note::
100+
101+
More information on AsyncAPI and Pub/Sub can be found at :ref:`pubsub`.
95102

96103
Summary
97104
-------

docs/source/configuration.rst

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ file whatever you wish; typical filenames end with ``.yml``.
1414
pygeoapi configuration contains the following core sections:
1515

1616
- ``server``: server-wide settings
17+
- ``pubsub``: Publish-Subscribe settings (optional)
1718
- ``logging``: logging configuration
1819
- ``metadata``: server-wide metadata (contact, licensing, etc.)
1920
- ``resources``: dataset collections, processes and stac-collections offered by the server
@@ -90,6 +91,23 @@ For more information related to API design rules (the ``api_rules`` property in
9091
url_prefix: 'v{api_major}' # adds a /v1 prefix to all URL paths
9192
version_header: X-API-Version # add a response header of this name with the API version
9293
94+
``pubsub``
95+
^^^^^^^^^^
96+
97+
The ``pubsub`` section provides directives for enabling publication of CloudEvent messaages on item-based transactions
98+
99+
100+
.. code-block:: yaml
101+
102+
pubsub:
103+
name: MQTT
104+
broker:
105+
url: mqtt://localhost:1883
106+
channel: my/service/topic
107+
108+
.. seealso::
109+
:ref:`pubsub` for more information on Publish-Subscribe capabilities
110+
93111

94112
``logging``
95113
^^^^^^^^^^^

docs/source/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ reference documentation on all aspects of the project.
3939
openapi
4040
publishing/index
4141
transactions
42+
pubsub
4243
admin-api
4344
security
4445
plugins

docs/source/pubsub.rst

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
.. _pubsub:
2+
3+
Publish-Subscribe integration (Pub/Sub)
4+
=======================================
5+
6+
pygeoapi supports Publish-Subscribe (Pub/Sub) integration by implementing
7+
the `OGC API Publish-Subscribe Workflow - Part 1: Core`_ (draft) specification.
8+
9+
Pub/Sub integration can be enabled by defining a broker that pycsw can use to
10+
publish notifications on given topics using CloudEvents (as per the specification).
11+
12+
When enabled, core functionality of Pub/Sub includes:
13+
14+
- providing an AsyncAPI document (JSON and HTML)
15+
- providing the following links on the OGC API landing page:
16+
17+
- the broker link (``rel=hub`` link relation)
18+
- the AsyncAPI JSON link (``rel=service-desc`` link relation and ``type=application/asyncapi+json`` media type)
19+
- the AsyncAPI HTML link (``rel=service-doc`` link relation and ``type=text/html`` media type)
20+
21+
- sending a notification message on the following events:
22+
23+
- feature or record transactions (create, replace, update, delete)
24+
- process executions/job creation
25+
26+
AsyncAPI
27+
--------
28+
29+
`AsyncAPI`_ is the event-driven equivalent to :ref:`openapi`
30+
31+
The official AsyncAPI specification can be found on the `AsyncAPI`_ website. pygeoapi supports AsyncAPI version 3.0.0.
32+
33+
AsyncAPI is an optional capability in pygeoapi. To enable AsyncAPI, the following steps are required:
34+
35+
- defining a ``pubsub`` section in configuration (see :ref:`configuration` and :ref:`brokers` for more information)
36+
- generating an AsyncAPI document
37+
- setting the ``PYGEOAPI_ASYNCAPI`` environment variable
38+
39+
Creating the AsyncAPI document
40+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
41+
42+
The AsyncAPI document is a YAML or JSON configuration which is generated from the pygeoapi configuration, and describes the server information, channels and the message payloads structures.
43+
44+
To generate the AsyncAPI document, run the following:
45+
46+
.. code-block:: bash
47+
48+
pygeoapi asyncapi generate /path/to/my-pygeoapi-config.yml
49+
50+
This will dump the AsyncAPI document as YAML to your system's ``stdout``. To save to a file on disk, run:
51+
52+
.. code-block:: bash
53+
54+
pygeoapi asyncapi generate /path/to/my-pygeoapi-config.yml --output-file /path/to/my-pygeoapi-asyncapi.yml
55+
56+
To generate the AsyncAPI document as JSON, run:
57+
58+
.. code-block:: bash
59+
60+
pygeoapi asyncapi generate /path/to/my-pygeoapi-config.yml --format json --output-file /path/to/my-pygeoapi-asyncapi.json
61+
62+
.. note::
63+
Generate as YAML or JSON? If your AsyncAPI YAML definition is slow to render as JSON,
64+
saving as JSON to disk will help with performance at run-time.
65+
66+
.. note::
67+
The AsyncAPI document provides detailed information on query parameters, and dataset
68+
property names and their data types. Whenever you make changes to your pygeoapi configuration,
69+
always refresh the accompanying AsyncAPI document.
70+
71+
Validating the AsyncAPI document
72+
--------------------------------
73+
74+
To ensure your AsyncAPI document is valid, pygeoapi provides a validation
75+
utility that can be run as follows:
76+
77+
.. code-block:: bash
78+
79+
pygeoapi asyncapi validate /path/to/my-pygeoapi-asyncapi.yml
80+
81+
.. _brokers:
82+
83+
Brokers
84+
-------
85+
86+
The following protocols are supported:
87+
88+
MQTT
89+
^^^^
90+
91+
Example directive:
92+
93+
.. code-block:: yaml
94+
95+
pubsub:
96+
name: MQTT
97+
broker:
98+
url: mqtt://localhost:1883
99+
channel: messages/a/data # optional
100+
hidden: false # default
101+
102+
HTTP
103+
^^^^
104+
105+
Example directive:
106+
107+
.. code-block:: yaml
108+
109+
pubsub:
110+
name: HTTP
111+
broker:
112+
url: https://ntfy.sh
113+
channel: messages-a-data # optional
114+
hidden: true # default false
115+
116+
.. note::
117+
118+
For any Pub/Sub endpoints requiring authentication, encode the ``url`` value as follows:
119+
120+
* ``mqtt://username:password@localhost:1883``
121+
* ``https://username:password@localhost``
122+
123+
As with any section of the pygeoapi configuration, environment variables may be used as needed, for example
124+
to set username/password information in a URL. If ``pubsub.broker.url`` contains authentication, and
125+
``pubsub.broker.hidden`` is ``false``, the authentication information will be stripped from the URL
126+
before displaying it on the landing page.
127+
128+
.. note::
129+
130+
If a ``channel`` is defined, it is used as a prefix to the relevant OGC API endpoint used.
131+
132+
If a ``channel`` is not defined, only the relevant OGC API endpoint is used.
133+
134+
.. _`OGC API Publish-Subscribe Workflow - Part 1: Core`: https://docs.ogc.org/DRAFTS/25-030.html
135+
.. _`AsyncAPI`: https://www.asyncapi.com

locale/en/LC_MESSAGES/messages.po

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -736,3 +736,21 @@ msgstr ""
736736

737737
msgid "Instances"
738738
msgstr ""
739+
740+
msgid "Pub/Sub Notifications"
741+
msgstr ""
742+
743+
msgid "Pub/Sub broker"
744+
msgstr ""
745+
746+
msgid "Subscribe to notifications from this service"
747+
msgstr ""
748+
749+
msgid "AsyncAPI Definition"
750+
msgstr ""
751+
752+
msgid "The AsyncAPI document as HTML"
753+
msgstr ""
754+
755+
msgid "The AsyncAPI document as JSON"
756+
msgstr ""

pygeoapi/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# Authors: Tom Kralidis <tomkralidis@gmail.com>
44
# Ricardo Garcia Silva <ricardo.garcia.silva@geobeyond.it>
55
#
6-
# Copyright (c) 2021 Tom Kralidis
6+
# Copyright (c) 2026 Tom Kralidis
77
# Copyright (c) 2023 Ricardo Garcia Silva
88
# Copyright (c) 2025 Angelos Tzotsos
99
#
@@ -38,6 +38,8 @@
3838
from importlib.metadata import entry_points
3939
except ImportError:
4040
from importlib_metadata import entry_points
41+
42+
from pygeoapi.asyncapi import asyncapi
4143
from pygeoapi.config import config
4244
from pygeoapi.openapi import openapi
4345

@@ -110,3 +112,4 @@ def serve(ctx, server):
110112

111113
cli.add_command(config)
112114
cli.add_command(openapi)
115+
cli.add_command(asyncapi)

0 commit comments

Comments
 (0)