Loading…
Loading…
Detailed technical documentation on creating, activating, and managing service versions, including draft creation, activation, rollback, and route
The Service Version Management component provides the data-layer logic for the lifecycle of an API service's versions. It enables API publishers to iterate on a service by creating new, isolated "draft" versions, modifying them, and then activating a chosen version to handle live traffic.
This component solves the problem of safely evolving an API without disrupting existing consumers. It ensures that the transition from one version to another is an atomic operation, including the critical step of updating the API Gateway's routing table.
The primary functions are:
This component is an internal part of the administrative platform, typically invoked by higher-level services that expose this functionality through the Admin API. Its inputs are service and version identifiers, and its outputs are changes to the underlying database, including service version state and the runtime routes that direct traffic.
Service versions are managed as records in the s2r_service_version database table. Each version belongs to a single service and has a unique version number, a status (draft, active, archived), and a flag (is_active) indicating if it is the currently live version.
A new version is created as a draft by cloning an existing version. This allows API publishers to modify a service's configuration, operations, and mappings in isolation before making it live.
The process, executed by createDraftVersion, is as follows:
Source Version Resolution: The operation requires a source version to clone. If a sourceVersionId is not explicitly provided, the system automatically selects a source in the following order of preference:
active version of the service.version_no.
If no source can be found, the operation fails.Pre-condition Check: The system verifies that the service does not already have a version with the status draft. A service can only have one draft at a time. If an existing draft is found, the operation fails.
Version Cloning: A new s2r_service_version record is created with a new UUID, the next available version_no, and its status set to draft.
Property Inheritance: The new draft inherits critical properties from the source version to ensure continuity and reduce reconfiguration. This includes:
wsdl_artifact_id), which is essential for certain service types.s2r_operation records) are duplicated for the new version.soap_action, rest_method, rest_path).request_schema, response_schema, fault_schema).binding_style) and SOAP headers (operation_headers).timeout_ms, retry_count, and debug_enabled.callback_path and callback_auth_mode.s2r_operation_mapping) for each operation is also cloned, ensuring that request and response transformations are preserved in the new draft.The following diagram illustrates the draft creation flow:
flowchart TD
subgraph Create Draft Version
A[Start: serviceId, sourceVersionId?] --> B{sourceVersionId provided?};
B -- Yes --> C[Verify sourceVersionId exists];
B -- No --> D[Find active or latest version];
C --> E[Set as sourceVersion];
D --> E;
E --> F[Check for existing draft];
F -- Exists --> G[Fail: "draft version already exists"];
F -- None --> H[Create new s2r_service_version row<br>(status='draft')];
H --> I[Copy wsdl_artifact_id from source];
I --> J[Query all operations from source version];
J --> K{For each source operation};
K -- Clone --> L[Create new operation row for draft version];
L --> M[Copy properties: schemas, binding_style, headers, async settings, etc.];
M --> N[Copy active transformation mapping];
N --> K;
K -- Done --> O[End: Return VersionDraftResult];
endIMPORTANT
The cloning process is designed to create a near-identical but independent copy. This ensures that an asynchronous operation in the source version remains asynchronous in the new draft, and that all operational settings are preserved as a starting point for further changes.
Activating a version makes it the single, live version for a service. This is an atomic operation that updates both the service's versioning state and the API Gateway's routing configuration. The activate and rollback functions both use this same underlying mechanism.
The activation process is as follows:
is_active = false). The previously active version has its status changed to archived.is_active = true) and its status is set to active. The parent service's status is also updated to active.s2r_runtime_route) for the service are deleted from the routing table.direction, environment, rest_method, and rest_path. If a collision is detected, the entire activation operation is rolled back to prevent one service from unintentionally "stealing" a route from another.s2r_runtime_route table, making the operation's endpoint live.The following diagram illustrates the sequence of events during activation:
sequenceDiagram
participant P as API Publisher
participant A as Admin API
participant L as Version Activation Logic
participant DB as Platform Database
P->>A: Activate Version(serviceId, versionId)
A->>L: Start Activation
L->>DB: Find current active version
L->>DB: Deactivate all versions for service
L->>DB: Activate target version (is_active=true, status='active')
L->>DB: Delete existing runtime routes for service
L->>DB: Get enabled operations for new version
DB-->>L: Operation details
L->>L: Check for route collisions with other services
alt Collision Found
L-->>A: Activation Failed (Error)
A-->>P: Activation Failed
else No Collision
L->>DB: Publish new runtime routes
DB-->>L: Routes published
L-->>A: Activation Succeeded
A-->>P: Activation Succeeded
endNOTE
The rollback function is an alias for activate. It follows the exact same technical process. The only difference is that the result of the operation will indicate the action was a "rollback", which can be useful for auditing purposes.
A service version can be linked to a record of an OpenAPI import. This creates a clear line of provenance from the live service version back to the specific OpenAPI specification file that was used to define it.
The updateOpenapiImportId function updates this association.
openapiImportId creates the link.null value clears any existing link.The component exposes several methods for managing service versions. These are typically not called directly by end-users but are foundational to the Admin API.
createDraftVersionCreates a new draft version by cloning an existing version.
| Parameter | Type | Required | Description |
|---|---|---|---|
serviceId | UUID | Yes | The ID of the service for which to create a draft. |
sourceVersionId | UUID | No | The ID of the version to clone. If null, the system automatically selects the active or latest version. |
actor | String | Yes | The identifier of the user or system performing the action. Defaults to "system" if blank. |
VersionDraftResult containing the IDs and numbers of the new and source versions.IllegalArgumentException: If the serviceId or sourceVersionId (if provided) is not found.IllegalStateException: If a draft version already exists for the service.activateActivates a specific version of a service, making it the live version.
| Parameter | Type | Required | Description |
|---|---|---|---|
serviceId | UUID | Yes | The ID of the service. |
versionId | UUID | Yes | The ID of the version to activate. |
actor | String | Yes | The identifier of the user or system performing the action. Defaults to "system" if blank. |
VersionActivationResult containing details of the activation, including the previously active version ID.IllegalArgumentException if the service version is not found.rollbackRolls back to a previous version of a service. This is functionally identical to activate.
| Parameter | Type | Required | Description |
|---|---|---|---|
serviceId | UUID | Yes | The ID of the service. |
versionId | UUID | Yes | The ID of the version to activate (roll back to). |
actor | String | Yes | The identifier of the user or system performing the action. Defaults to "system" if blank. |
VersionActivationResult with the action field set to "rollback".IllegalArgumentException if the service version is not found.updateOpenapiImportIdAssociates a service version with an OpenAPI import record.
| Parameter | Type | Required | Description |
|---|---|---|---|
serviceId | UUID | Yes | The ID of the service. |
versionId | UUID | Yes | The ID of the version to update. |
openapiImportId | UUID | No | The ID of the s2r_openapi_import record. If null, the link is cleared. |
VersionRecord.IllegalArgumentException: If the service version is not found.IllegalStateException: If the openapiImportId does not correspond to an existing import record.findByServiceIdRetrieves all versions for a given service.
| Parameter | Type | Required | Description |
|---|---|---|---|
serviceId | UUID | Yes | The ID of the service. |
List<VersionRecord> ordered by version_no descending.findByIdRetrieves a single, specific version.
| Parameter | Type | Required | Description |
|---|---|---|---|
serviceId | UUID | Yes | The ID of the service. |
versionId | UUID | Yes | The ID of the version to retrieve. |
Optional<VersionRecord> which is empty if the version is not found.Represents a single version of a service.
| Field | Type | Description |
|---|---|---|
id | UUID | The unique identifier for the service version. |
version_no | int | The sequential, human-readable version number. |
status | String | The current lifecycle state (e.g., draft, active, archived). |
is_active | boolean | true if this is the currently live version for the service. |
created_at | OffsetDateTime | The timestamp when the version was created. |
created_by | String | The user or system that created the version. |
openapi_import_id | UUID | Optional. The ID of the associated OpenAPI import record. |
The result of a createDraftVersion operation.
| Field | Type | Description |
|---|---|---|
serviceId | UUID | The ID of the parent service. |
newVersionId | UUID | The ID of the newly created draft version. |
newVersionNumber | int | The version number of the new draft. |
sourceVersionId | UUID | The ID of the version that was cloned. |
operationsCopied | int | The number of operations copied from the source version. |
The result of an activate or rollback operation.
| Field | Type | Description |
|---|---|---|
serviceId | UUID | The ID of the parent service. |
versionId | UUID | The ID of the version that was just activated. |
previousActiveVersionId | UUID | Optional. The ID of the version that was active before this operation. |
routesPublished | int | The number of runtime routes published for the newly activated version. |
action | String | The action performed, either "activate" or "rollback". |
| Error Message / Condition | Trigger | Meaning & Resolution |
|---|---|---|
IllegalStateException: "draft version already exists" | Calling createDraftVersion for a service that already has a version with status = 'draft'. | A service can only have one draft at a time. To create a new draft, you must first either activate or delete the existing one. |
IllegalArgumentException: "service not found" | Providing a serviceId that does not exist in the database. | Verify that the serviceId is correct and corresponds to an existing service. |
IllegalArgumentException: "service version not found" | Providing a versionId that does not exist for the given serviceId. | Verify that the versionId is correct and belongs to the specified service. |
IllegalArgumentException: "source version not found" | Calling createDraftVersion with an explicit sourceVersionId that doesn't exist, or for a service with no versions at all. | Ensure the sourceVersionId is valid. If not providing one, ensure the service has at least one existing version to clone from. |
IllegalStateException: "openapi import not found: <id>" | Calling updateOpenapiImportId with a UUID that does not match any record in the s2r_openapi_import table. | Verify that the openapiImportId is correct and that the corresponding OpenAPI specification has been imported into the system. |
| Activation fails with rollback | An enabled operation in the version being activated has a route (rest_method + rest_path) that is already in use by a different service. | This is a safety mechanism to prevent route hijacking. Identify the conflicting operation and change its REST method or path. Alternatively, resolve the conflict in the other service. |