Skip to content

Commit

Permalink
docs: decision record about API versioning
Browse files Browse the repository at this point in the history
  • Loading branch information
paullatzelsperger committed Nov 9, 2023
1 parent 2dce1f0 commit acb830d
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Consistent Versioning of external APIs

## Decision

Going forward, all our external APIs will be versioned consistently across all endpoints and controllers. This means,
that the
Management API (to name a prominent example) will have the version encoded same URL within the same major version.

## Rationale

Currently, every module that contributes an API can have its own versioning model. For example, at the time of writing
some APIs are available under `/v2/...`, some are available under `/v3/...` and some without a version specifier.

This can be confusing to developers who want to consume the API, because they not only need different base paths for
every API, they also need to re-check every endpoint when a new version of EDC is released, because every API can change
individually.

Therefor we will use consistent versioning across _all_ client-facing APIs. At the time of writing, this includes just
the Management API.

## Approach

### Versioning scheme

Following the general semantics of SemVer, we will distinguish between a breaking change (major version bump) and
non-breaking and patch changes (minor/patch version bump). The major version will be represented in the URL:

```
https://some.host.com/api/management/v4/...
```

This means, client code only needs to be updated on major version changes of an API.

> Only major versions are represented in the URL
> Minor or patch updates will **not** be represented in the URL, and we will **not** host multiple minor/patch versions
> of an API at any given time.
Consequently, when multiple major versions of an API are available, every versioned URL (e.g. `/v3/assets`) effectively
contains the _latest_ version, so for instance `/v3/assets` would effectively point to version `3.1.4` of the Management
API.

> The same exact version is used for the entire Management API, we do **not** version independent modules or controllers
> The version of an API is independent of the version of EDC.
### Delegation mechanism for controllers

Not every endpoint changes from version to version, that means we will have to make the _same_ controller available
under _multiple_ URL paths as we do not want to duplicate controllers. There are several potential ways we could make
this work:

- Declare the `@Path` as [wildcard](https://docs.oracle.com/javaee/7/api/javax/ws/rs/Path.html)
- implement a custom interceptor, that parses the path and delegates to the correct controller

These are as yet untested and need further investigation with regard to the following aspects:

- do the come up as individual endpoints in the OpenAPI documentation?
- is there a significant impact w.r.t. resource consumption?

### Storing and publishing version information

A new endpoint will be available that provides exact information about the version of the API. The path and the response
schema is TBD.

The version of an API must be stored in a file that is available at runtime. Every change to an API must increase that
version property. The `gradle.properties` file would be the obvious choice, however we would have to craft a way to
access that information at runtime.

### Publishing APIs to SwaggerHub

Ultimately, we will move away from publishing our APIs under the EDC version, and will publish them only under their
own version. Every update (major, minor, patch,...) will be published to SwaggerHub.
For this, we will have to update our Swagger-publish workflow quite significantly and read the
API [version information](#storing-and-publishing-version-information).

### Maintenance/deprecation model

As a standard M/O EDC will expose at most two versions of an API at any given time. The older one must be marked
as `deprecated` both in code and in Swagger.

All maintenance (bugfixes, patches, improvements) will **only** be made to the most recent API. Deprecated APIs will
**not** receive any maintenance.
2 changes: 2 additions & 0 deletions docs/developer/decision-records/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,5 @@
- [2023-08-01 Default datasource](2023-08-01-default-datasource)
- [2023-08-07 Generic properties](./2023-08-07-generic-properties)
- [2023-09-07 Policy Monitor](./2023-09-07-policy-monitor)
- [2023-10-04 JSON-LD Scopes](./2023-10-04-json-ld-scopes)
- [2023-11-09 API Versioning](./2023-11-09-api-versioning)
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@

@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
@Path("/v3/assets")
@Path("/{s:.*}/assets")
public class AssetApiController implements AssetApi {
private final TypeTransformerRegistry transformerRegistry;
private final AssetService service;
Expand Down

0 comments on commit acb830d

Please sign in to comment.