yuzutech / kroki

Creates diagrams from textual descriptions!
https://kroki.io
MIT License
2.89k stars 216 forks source link

Service discovery #1423

Open ggrossetie opened 1 year ago

ggrossetie commented 1 year ago

The goal is to allow the gateway server to register additional diagram libraries (that are not built-in). One of the requirement will be to adhere to the Kroki companion container API specification (not yet available).

Proposal

Discovery

When the gateway server starts, it will probe the seed addresses by connecting to each address and attempting to identify the service. If successful, it will register a new service.

discovery.seed_resolver.timeout: 5s
discovery.seed_resolver.max_retry: 5
discovery.seed_hosts:
  - 192.168.1.10:1234
  - 192.168.1.11 
  - seeds.mydomain.com 

This solution implies that the service must provide information (at least a unique name, a version, and a list of supported formats).

Static registration

Alternatively, we could explicitly register services:

services:
  - name: sankey
    version: '1.2.3'
    endpoint: https://my.domain.org/sankey
    formats:
      - png
      - svg

In this case, the service does not have to expose an API that provides information.

Dynamic registration

We could also support dynamic registration. In this case, the companion service will be responsible for registering itself by sending a request to the gateway server.

POST https://my.kroki/services

{
  "name": "mscgen",
  "version": "1.2.3",
  "formats": ["png", "svg"]
}

Since Kroki is stateless, registry is held in memory. As a result, the companion service is responsible for registering again in case the gateway server is restarted.

For this reasons, services should send a heartbeat:

PUT https://my.kroki/services/mscgen/heartbeat

A service that receives a 404 during a heartbeat could then register again.

The gateway service will provide information about a registred service:

GET https://my.kroki/services/mscgen

{
  "name": "mscgen",
  "version": "1.2.3",
  "formats": ["png", "svg"],
  "created_at": "2023-01-01T15:50:05.815479Z",
  "updated_at": "2023-01-01T15:50:05.815479Z",
  "last_activity_at": "2023-01-01T18:55:04.187568Z"
}

Note: Last activity date is the last time a service sent a heartbeat or respond to a request from the gateway server.

I will also provide a list of all services currently registered:

GET https://my.kroki/services
[
  {
    "name": "mscgen",
    "version": "1.2.3",
    "_links": [
      {
        "rel": "self",
        "href": "/services/mscgen",
        "method": "GET"
      }
    ]
  }
]  

Unregister

A service can unregister (for instance when the service is shutting down) using:

DELETE https://my.kroki/services/mscgen
copyrights commented 1 year ago

I would add the possibility for an example key (may optional) .

GET https://my.kroki/services/blockdiag

{
  "name": "BlockDiag",
  "version": "1.2.3",
  "formats": ["png", "svg"],
  "example": "blockdiag {\n  Kroki -> generates -> \"Block diagrams\";\n  Kroki -> is -> \"very easy!\";\n\n  Kroki [color = \"greenyellow\"];\n  \"Block diagrams\" [color = \"pink\"];\n  \"very easy!\" [color = \"orange\"];\n}",
  "created_at": "2023-01-01T15:50:05.815479Z",
  "updated_at": "2023-01-01T15:50:05.815479Z",
  "last_activity_at": "2023-01-01T18:55:04.187568Z"
}
ggrossetie commented 1 year ago

It's interesting to note that Vert.x has a service discovery library: https://vertx.io/docs/vertx-service-discovery/java/ One downside is that it would require companion service/container to use an EventBus client to register: https://github.com/vert-x3/vertx-eventbus-bridge-clients

Having said that, we could offer a REST API as a bridge and still leverage Vert.x service discovery library.

I would add the possibility for an example key (may optional) .

What would be the purpose?

copyrights commented 1 year ago

to provide an example for a client application e.g. https://kroki.io. When you build something like that you may don't want to change your code for every new service provided via the api.