From 2eda64e2fa2e0ac61ee174d692c3467e08095f1c Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Sun, 4 Jan 2026 00:18:57 +0530 Subject: [PATCH 1/2] Implement service publish/update flow with conflict handling --- ballerina/listener.bal | 2 - ballerina/service.bal | 89 +++++++++++++++++++++--------------------- 2 files changed, 45 insertions(+), 46 deletions(-) diff --git a/ballerina/listener.bal b/ballerina/listener.bal index 07b57be..8ddd7b7 100644 --- a/ballerina/listener.bal +++ b/ballerina/listener.bal @@ -22,11 +22,9 @@ public class Listener { } public function gracefulStop() returns error? { - check removeExistingServices(apimClient); } public function immediateStop() returns error? { - check removeExistingServices(apimClient); } public function detach(service object {} s) returns error? { diff --git a/ballerina/service.bal b/ballerina/service.bal index 1baee86..d916955 100644 --- a/ballerina/service.bal +++ b/ballerina/service.bal @@ -17,7 +17,6 @@ import ballerina/http; import ballerina/jballerina.java; import ballerina/oauth2; -import ballerina/log; configurable string serviceUrl = "https://apis.wso2.com/api/service-catalog/v1"; configurable string username = ""; @@ -33,8 +32,6 @@ configurable string[] scopes = ["service_catalog:service_view", "apim:api_view", listener Listener 'listener = new Listener(port); -final string[] publishedServiceIds = []; - Client apimClient = check new (serviceUrl = serviceUrl, config = { auth: { username, @@ -49,37 +46,9 @@ Client apimClient = check new (serviceUrl = serviceUrl, config = { }); function publishArtifacts(ServiceArtifact[] artifacts) returns error? { - error? e = (); foreach ServiceArtifact artifact in artifacts { - Service|error res = apimClient->/services.post({ - serviceMetadata: { - name: artifact.name, - description: artifact.description, - 'version: artifact.version, - serviceKey: artifact.serviceKey, - serviceUrl: artifact.serviceUrl, - definitionType: artifact.definitionType, - securityType: artifact.securityType, - mutualSSLEnabled: artifact.mutualSSLEnabled, - definitionUrl: artifact.definitionUrl - }, - inlineContent: artifact.definitionFileContent - }); - - // If there is an error, wait until other artifacts get published - if res is error { - e = res; - continue; - } - - string? id = res?.id; - if id == () { - continue; - } - - publishedServiceIds.push(id); + _ = check publishOrUpdateService(artifact); } - return e; } isolated function getArtifacts() returns ServiceArtifact[] = @java:Method { @@ -101,18 +70,50 @@ function getServerCert(string? serverCert) returns http:ClientSecureSocket? { return {enable: false}; } -function removeExistingServices(Client apimClient) returns error? { - foreach string id in publishedServiceIds { - http:Response|error response = apimClient->/services/[id].delete(); - if response is error { - log:printError("Error occurred while deleting the service: ", response, serviceId = id); - return response; - } +function getServiceIdByKey(string serviceKey) returns string|error|() { + ServiceList res = check apimClient->/services.get('key = serviceKey); + Service[] services = res.list ?: []; + return services.length() > 0 ? services[0].id : (); +} - if response.statusCode != 204 { - string responseMessage = (check response.getJsonPayload()).toJsonString(); - log:printError("Failed to delete service: ", serviceId = id, message = responseMessage); - return error("Failed to delete the service with id: " + id, cause = responseMessage); - } +function updateExistingService(ServiceArtifact artifact) returns Service|error { + string|() serviceId = check getServiceIdByKey(artifact.serviceKey); + if serviceId is () { + return error("Service exists but serviceId could not be resolved"); + } + return check apimClient->/services/[serviceId].put({ + serviceMetadata: { + name: artifact.name, + description: artifact.description, + 'version: artifact.version, + serviceKey: artifact.serviceKey, + serviceUrl: artifact.serviceUrl, + definitionType: artifact.definitionType, + securityType: artifact.securityType, + mutualSSLEnabled: artifact.mutualSSLEnabled, + definitionUrl: artifact.definitionUrl + }, + inlineContent: artifact.definitionFileContent + }); +} + +function publishOrUpdateService(ServiceArtifact artifact) returns Service|error { + Service|error res = apimClient->/services.post({ + serviceMetadata: { + name: artifact.name, + description: artifact.description, + 'version: artifact.version, + serviceKey: artifact.serviceKey, + serviceUrl: artifact.serviceUrl, + definitionType: artifact.definitionType, + securityType: artifact.securityType, + mutualSSLEnabled: artifact.mutualSSLEnabled, + definitionUrl: artifact.definitionUrl + }, + inlineContent: artifact.definitionFileContent + }); + if res is http:ClientRequestError && res.detail().statusCode == 409 { + return updateExistingService(artifact); } + return res; } From f757d373a5b13ca794f16f3a62e411a80dbe58e4 Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Mon, 5 Jan 2026 14:54:16 +0530 Subject: [PATCH 2/2] Fix review suggestion --- ballerina/service.bal | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/ballerina/service.bal b/ballerina/service.bal index d916955..09fd94d 100644 --- a/ballerina/service.bal +++ b/ballerina/service.bal @@ -76,29 +76,10 @@ function getServiceIdByKey(string serviceKey) returns string|error|() { return services.length() > 0 ? services[0].id : (); } -function updateExistingService(ServiceArtifact artifact) returns Service|error { +function publishOrUpdateService(ServiceArtifact artifact) returns Service|error { string|() serviceId = check getServiceIdByKey(artifact.serviceKey); if serviceId is () { - return error("Service exists but serviceId could not be resolved"); - } - return check apimClient->/services/[serviceId].put({ - serviceMetadata: { - name: artifact.name, - description: artifact.description, - 'version: artifact.version, - serviceKey: artifact.serviceKey, - serviceUrl: artifact.serviceUrl, - definitionType: artifact.definitionType, - securityType: artifact.securityType, - mutualSSLEnabled: artifact.mutualSSLEnabled, - definitionUrl: artifact.definitionUrl - }, - inlineContent: artifact.definitionFileContent - }); -} - -function publishOrUpdateService(ServiceArtifact artifact) returns Service|error { - Service|error res = apimClient->/services.post({ + return apimClient->/services.post({ serviceMetadata: { name: artifact.name, description: artifact.description, @@ -112,8 +93,19 @@ function publishOrUpdateService(ServiceArtifact artifact) returns Service|error }, inlineContent: artifact.definitionFileContent }); - if res is http:ClientRequestError && res.detail().statusCode == 409 { - return updateExistingService(artifact); } - return res; + return apimClient->/services/[serviceId].put({ + serviceMetadata: { + name: artifact.name, + description: artifact.description, + 'version: artifact.version, + serviceKey: artifact.serviceKey, + serviceUrl: artifact.serviceUrl, + definitionType: artifact.definitionType, + securityType: artifact.securityType, + mutualSSLEnabled: artifact.mutualSSLEnabled, + definitionUrl: artifact.definitionUrl + }, + inlineContent: artifact.definitionFileContent + }); }