From 741243af7cc69aef62f7a13af5de9d66f1fb48f7 Mon Sep 17 00:00:00 2001 From: aashikam Date: Mon, 3 Jun 2024 23:34:54 +0530 Subject: [PATCH 01/12] [Automated] Update the toml files --- ballerina/Ballerina.toml | 6 +++--- ballerina/Dependencies.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ballerina/Ballerina.toml b/ballerina/Ballerina.toml index a9fb8cb9..c2a9ca76 100644 --- a/ballerina/Ballerina.toml +++ b/ballerina/Ballerina.toml @@ -2,7 +2,7 @@ distribution = "2201.8.0" org = "ballerinax" name = "salesforce" -version = "8.0.1" +version = "8.0.2" export = ["salesforce", "salesforce.bulk", "salesforce.soap"] license= ["Apache-2.0"] authors = ["Ballerina"] @@ -17,10 +17,10 @@ observabilityIncluded = true graalvmCompatible = true [[platform.java17.dependency]] -path = "../native/build/libs/salesforce-native-8.0.1.jar" +path = "../native/build/libs/salesforce-native-8.0.2-SNAPSHOT.jar" groupId = "io.ballerinax" artifactId = "salesforce" -version = "8.0.1" +version = "8.0.2-SNAPSHOT" [[platform.java17.dependency]] groupId = "com.opencsv" diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 0ff4b82c..43a55be3 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -377,7 +377,7 @@ modules = [ [[package]] org = "ballerinax" name = "salesforce" -version = "8.0.1" +version = "8.0.2" dependencies = [ {org = "ballerina", name = "http"}, {org = "ballerina", name = "io"}, From 60213a3e8c5de7144868c81bd0bd6e12969caa75 Mon Sep 17 00:00:00 2001 From: aashikam Date: Mon, 3 Jun 2024 23:41:14 +0530 Subject: [PATCH 02/12] Add support for pagination --- ballerina/client.bal | 46 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/ballerina/client.bal b/ballerina/client.bal index 9f3b57fc..833835e1 100644 --- a/ballerina/client.bal +++ b/ballerina/client.bal @@ -27,6 +27,7 @@ import ballerinax/salesforce.utils; public isolated client class Client { private final http:Client salesforceClient; + private map sfLocators = {}; # Initializes the connector. During initialization you can pass either http:BearerTokenConfig if you have a bearer # token or http:OAuth2RefreshTokenGrantConfig if you have Oauth tokens. @@ -651,18 +652,55 @@ public isolated client class Client { } - # Get query job results + # Get bulk query job results + # # + bulkJobId - Id of the bulk job - # + return - string[][] if successful else `error` - isolated remote function getQueryResult(string bulkJobId) + # + maxRecords - The maximum number of records to retrieve per set of results for the query + # + return - The resulting string[][] if successful else `error` + isolated remote function getQueryResult(string bulkJobId, int? maxRecords = ()) returns string[][]|error { - string path = utils:prepareUrl([API_BASE_PATH, JOBS, QUERY, bulkJobId, RESULT]); + + string path = ""; + string batchingParams = ""; + + // Max records value is user given + if maxRecords != () { + lock { + if self.sfLocators.hasKey(bulkJobId) { + string locator = self.sfLocators.get(bulkJobId); + if locator is "null" { + return []; + } + batchingParams = string `results?maxRecords=${maxRecords}&locator=${locator}`; + } else { + batchingParams = string `results?maxRecords=${maxRecords}`; + } + } + path = utils:prepareUrl([API_BASE_PATH, JOBS, QUERY, bulkJobId, batchingParams]); + // Max records value default, we might not know when the locator comes + } else if maxRecords == () { + lock { + if self.sfLocators.hasKey(bulkJobId) { + string locator = self.sfLocators.get(bulkJobId); + if locator is "null" { + return []; + } + batchingParams = string `results?locator=${locator}`; + } else { + path = utils:prepareUrl([API_BASE_PATH, JOBS, QUERY, bulkJobId, RESULT]); + } + } + } + http:Response response = check self.salesforceClient->get(path); if response.statusCode == 200 { string textPayload = check response.getTextPayload(); if textPayload == "" { return []; } + lock { + self.sfLocators[bulkJobId] = check response.getHeader("sforce-locator"); + } string[][] result = check parseCsvString(textPayload); return result; } else { From 538e42fd0f0ea43dd9e33b27174acf5b285d1f7e Mon Sep 17 00:00:00 2001 From: Arshika Mohottige Date: Tue, 4 Jun 2024 20:01:26 +0530 Subject: [PATCH 03/12] Update ballerina/client.bal Co-authored-by: Nipuna Ransinghe --- ballerina/client.bal | 1 - 1 file changed, 1 deletion(-) diff --git a/ballerina/client.bal b/ballerina/client.bal index 833835e1..b0af8ab0 100644 --- a/ballerina/client.bal +++ b/ballerina/client.bal @@ -663,7 +663,6 @@ public isolated client class Client { string path = ""; string batchingParams = ""; - // Max records value is user given if maxRecords != () { lock { if self.sfLocators.hasKey(bulkJobId) { From cde155caf513a243aecd3800c89cffe1ba51a64b Mon Sep 17 00:00:00 2001 From: aashikam Date: Tue, 4 Jun 2024 22:32:19 +0530 Subject: [PATCH 04/12] Add changelog.md --- changelog.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 changelog.md diff --git a/changelog.md b/changelog.md new file mode 100644 index 00000000..764892fc --- /dev/null +++ b/changelog.md @@ -0,0 +1,14 @@ +# Change Log +This file contains all the notable changes done to the Ballerina Salesforce package through the releases. + +## [Unreleased] + +### Added + +- [[#6577] Add support for pagination/chunking](https://github.com/ballerina-platform/ballerina-library/issues/6577) + +## [8.0.1] - 2024-05-29 + +### Fixed + +- [[#6556] Fixed connector returning invalid CSV data when values contain new lines](https://github.com/ballerina-platform/ballerina-library/issues/6556) From 4a800d8a5ff610af9b5135da1594fdb79fc92aec Mon Sep 17 00:00:00 2001 From: aashikam Date: Tue, 4 Jun 2024 22:35:38 +0530 Subject: [PATCH 05/12] Delete main.bal --- ballerina/main.bal | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 ballerina/main.bal diff --git a/ballerina/main.bal b/ballerina/main.bal deleted file mode 100644 index 68a42f4c..00000000 --- a/ballerina/main.bal +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 2021 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. -// -// WSO2 Inc. licenses this file to you under the Apache License, -// Version 2.0 (the "License"); you may not use this file except -// in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. From ccfdfd1fa6e78f961a4b3eb22f97e6fa6f2345f0 Mon Sep 17 00:00:00 2001 From: aashikam Date: Tue, 4 Jun 2024 22:53:51 +0530 Subject: [PATCH 06/12] Add documentation improvements --- README.md | 2 +- ballerina/Module.md | 10 +++++----- ballerina/Package.md | 10 +++++----- ballerina/client.bal | 6 +++--- ballerina/modules/bulk/Module.md | 8 ++++---- ballerina/modules/soap/Module.md | 8 ++++---- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 178c2a6f..441a1455 100644 --- a/README.md +++ b/README.md @@ -114,7 +114,7 @@ bal run The `salesforce` connector provides practical examples illustrating usage in various scenarios. Explore these examples below, covering use cases like creating sObjects, retrieving records, and executing bulk operations. -1. [Salesforce REST API use cases](https://github.com/ballerina-platform/module-ballerinax-sfdc/tree/master/examples/rest_api_usecases) - How to employ REST API of Salesforce to carryout varies tasks. +1. [Salesforce REST API use cases](https://github.com/ballerina-platform/module-ballerinax-sfdc/tree/master/examples/rest_api_usecases) - How to employ REST API of Salesforce to carryout various tasks. 2. [Salesforce Bulk API use cases](https://github.com/ballerina-platform/module-ballerinax-sfdc/tree/master/examples/bulk_api_usecases) - How to employ Bulk API of Salesforce to execute Bulk jobs. diff --git a/ballerina/Module.md b/ballerina/Module.md index 9244c15c..7d5e9c38 100644 --- a/ballerina/Module.md +++ b/ballerina/Module.md @@ -16,16 +16,16 @@ Ballerina Salesforce connector supports [Salesforce v59.0 REST API](https://deve Create Connected Apps - - Here we will be using https://test.salesforce.com as we are using sandbox enviorenment. Users can use https://login.salesforce.com for normal usage. + - Here we will be using https://test.salesforce.com as we are using sandbox environment. Users can use https://login.salesforce.com for normal usage. Create Connected Apps -4. After the creation user can get consumer key and secret through clicking on the `Manage Consume Details` button. +4. After the creation user can get consumer key and secret through clicking on the `Manage Consumer Details` button. Consumer Secrets 5. Next step would be to get the token. - - Log in to salesforce in your prefered browser and enter the following url. + - Log in to salesforce in your preferred browser and enter the following url. ``` https://.salesforce.com/services/oauth2/authorize?response_type=code&client_id=&redirect_uri= ``` @@ -71,7 +71,7 @@ salesforce:ConnectionConfig config = { } }; -salesforce:Client salesforce = new(config); +salesforce:Client salesforce = check new (config); ``` #### Step 3: Invoke connector operation @@ -99,7 +99,7 @@ bal run The `salesforce` connector provides practical examples illustrating usage in various scenarios. Explore these examples below, covering use cases like creating sObjects, retrieving records, and executing bulk operations. -1. [Salesforce REST API use cases](https://github.com/ballerina-platform/module-ballerinax-sfdc/tree/master/examples/rest_api_usecases) - How to employ REST API of Salesforce to carryout varies tasks. +1. [Salesforce REST API use cases](https://github.com/ballerina-platform/module-ballerinax-sfdc/tree/master/examples/rest_api_usecases) - How to employ REST API of Salesforce to carryout various tasks. 2. [Salesforce Bulk API use cases](https://github.com/ballerina-platform/module-ballerinax-sfdc/tree/master/examples/bulk_api_usecases) - How to employ Bulk API of Salesforce to execute Bulk jobs. diff --git a/ballerina/Package.md b/ballerina/Package.md index 755e9fc3..6e3c1808 100644 --- a/ballerina/Package.md +++ b/ballerina/Package.md @@ -16,16 +16,16 @@ Ballerina Salesforce connector supports [Salesforce v59.0 REST API](https://deve Create Connected Apps - - Here we will be using https://test.salesforce.com as we are using sandbox enviorenment. Users can use https://login.salesforce.com for normal usage. + - Here we will be using https://test.salesforce.com as we are using sandbox environment. Users can use https://login.salesforce.com for normal usage. Create Connected Apps -4. After the creation user can get consumer key and secret through clicking on the `Manage Consume Details` button. +4. After the creation user can get consumer key and secret through clicking on the `Manage Consumer Details` button. Consumer Secrets 5. Next step would be to get the token. - - Log in to salesforce in your prefered browser and enter the following url. + - Log in to salesforce in your preferred browser and enter the following url. ```https://.salesforce.com/services/oauth2/authorize?response_type=code&client_id=&redirect_uri=``` - Allow access if an alert pops up and the browser will be redirected to a Url like follows. @@ -65,7 +65,7 @@ salesforce:ConnectionConfig config = { } }; -salesforce:Client salesforce = new(config); +salesforce:Client salesforce = check new (config); ``` #### Step 3: Invoke connector operation @@ -97,7 +97,7 @@ The `salesforce` integration samples illustrate its usage in various integration The `salesforce` connector provides practical examples illustrating usage in various scenarios. Explore these examples below, covering use cases like creating sObjects, retrieving records, and executing bulk operations. -1. [Salesforce REST API use cases](https://github.com/ballerina-platform/module-ballerinax-sfdc/tree/master/examples/rest_api_usecases) - How to employ REST API of Salesforce to carryout varies tasks. +1. [Salesforce REST API use cases](https://github.com/ballerina-platform/module-ballerinax-sfdc/tree/master/examples/rest_api_usecases) - How to employ REST API of Salesforce to carryout various tasks. 2. [Salesforce Bulk API use cases](https://github.com/ballerina-platform/module-ballerinax-sfdc/tree/master/examples/bulk_api_usecases) - How to employ Bulk API of Salesforce to execute Bulk jobs. diff --git a/ballerina/client.bal b/ballerina/client.bal index b0af8ab0..1d2a9ad0 100644 --- a/ballerina/client.bal +++ b/ballerina/client.bal @@ -91,7 +91,7 @@ public isolated client class Client { //Describe Organization # Lists summary details about each REST API version available. # - # + return - List of `Version` if successful. Else, the occured `error` + # + return - List of `Version` if successful. Else, the occurred `error` isolated remote function getApiVersions() returns Version[]|error { string path = utils:prepareUrl([BASE_PATH]); return check self.salesforceClient->get(path); @@ -401,10 +401,10 @@ public isolated client class Client { return check self.salesforceClient->get(path); } - # Executes up to 25 subrequests in a single request. + # Executes up to 25 sub-requests in a single request. # # + batchRequests - A record containing all the requests - # + haltOnError - If true, the request halts when an error occurs on an individual subrequest + # + haltOnError - If true, the request halts when an error occurs on an individual sub-request # + return - `BatchResult` if successful or else `error` isolated remote function batch(Subrequest[] batchRequests, boolean haltOnError = false) returns BatchResult|error { string path = utils:prepareUrl([API_BASE_PATH, COMPOSITE, BATCH]); diff --git a/ballerina/modules/bulk/Module.md b/ballerina/modules/bulk/Module.md index 76153f78..13ff25b5 100644 --- a/ballerina/modules/bulk/Module.md +++ b/ballerina/modules/bulk/Module.md @@ -15,16 +15,16 @@ This module supports [Salesforce Bulk API v1](https://developer.salesforce.com/d Create Connected Apps - - Here we will be using https://test.salesforce.com as we are using sandbox enviorenment. Users can use https://login.salesforce.com for normal usage. + - Here we will be using https://test.salesforce.com as we are using sandbox environment. Users can use https://login.salesforce.com for normal usage. Create Connected Apps -4. After the creation user can get consumer key and secret through clicking on the `Manage Consume Details` button. +4. After the creation user can get consumer key and secret through clicking on the `Manage Consumer Details` button. Consumer Secrets 5. Next step would be to get the token. - - Log in to salesforce in your prefered browser and enter the following url. + - Log in to salesforce in your preferred browser and enter the following url. `https://.salesforce.com/services/oauth2/authorize?response_type=code&client_id=&redirect_uri=` - Allow access if an alert pops up and the browser will be redirected to a Url like follows. `https://login.salesforce.com/?code=` @@ -64,7 +64,7 @@ bulk:ConnectionConfig sfConfig = { } }; -bulk:Client bulkClient = new (sfConfig); +bulk:Client bulkClient = check new (sfConfig); ``` ### Step 3: Invoke connector operation diff --git a/ballerina/modules/soap/Module.md b/ballerina/modules/soap/Module.md index 09126e46..bff3912f 100644 --- a/ballerina/modules/soap/Module.md +++ b/ballerina/modules/soap/Module.md @@ -15,16 +15,16 @@ This module supports [Salesforce v48.0 SOAP API Enterprise WDSL](https://develop Create Connected Apps - - Here we will be using https://test.salesforce.com as we are using sandbox enviorenment. Users can use https://login.salesforce.com for normal usage. + - Here we will be using https://test.salesforce.com as we are using sandbox environment. Users can use https://login.salesforce.com for normal usage. Create Connected Apps -4. After the creation user can get consumer key and secret through clicking on the `Manage Consume Details` button. +4. After the creation user can get consumer key and secret through clicking on the `Manage Consumer Details` button. Consumer Secrets 5. Next step would be to get the token. - - Log in to salesforce in your prefered browser and enter the following url. + - Log in to salesforce in your preferred browser and enter the following url. `https://.salesforce.com/services/oauth2/authorize?response_type=code&client_id=&redirect_uri=` - Allow access if an alert pops up and the browser will be redirected to a Url like follows. `https://login.salesforce.com/?code=` @@ -61,7 +61,7 @@ soap:ConnectionConfig config = { } }; -soap:Client salesforce = new(sfConfig); +soap:Client salesforce = check new (config); ``` ### Step 3: Invoke connector operation From 7ff22c77af81be4391187dbfa4726b9b30f942a7 Mon Sep 17 00:00:00 2001 From: Arshika Mohottige Date: Thu, 6 Jun 2024 06:24:27 +0530 Subject: [PATCH 07/12] Update ballerina/client.bal Co-authored-by: Nipuna Ransinghe --- ballerina/client.bal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ballerina/client.bal b/ballerina/client.bal index 1d2a9ad0..bdf255f2 100644 --- a/ballerina/client.bal +++ b/ballerina/client.bal @@ -677,7 +677,7 @@ public isolated client class Client { } path = utils:prepareUrl([API_BASE_PATH, JOBS, QUERY, bulkJobId, batchingParams]); // Max records value default, we might not know when the locator comes - } else if maxRecords == () { + } else { lock { if self.sfLocators.hasKey(bulkJobId) { string locator = self.sfLocators.get(bulkJobId); From 22a3a190f351f0b7e4a2571a02c853eb3c561697 Mon Sep 17 00:00:00 2001 From: aashikam Date: Thu, 6 Jun 2024 12:16:58 +0530 Subject: [PATCH 08/12] Add test for maxRecords --- ballerina/tests/bulk_csv_query.bal | 57 ++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/ballerina/tests/bulk_csv_query.bal b/ballerina/tests/bulk_csv_query.bal index ae6ac29c..55b3033d 100644 --- a/ballerina/tests/bulk_csv_query.bal +++ b/ballerina/tests/bulk_csv_query.bal @@ -65,6 +65,63 @@ function queryCsv() returns error? { } +@test:Config { + enable: true, + dependsOn: [insertCsvFromFile, insertCsv, insertCsvStringArrayFromFile, insertCsvStreamFromFile] +} +function queryCsvWithMaxRecords() returns error? { + runtime:sleep(delayInSecs); + log:printInfo("baseClient -> queryCsv"); + string queryStr = "SELECT Id, Name FROM Contact WHERE Title='Professor Level 02'"; + + BulkCreatePayload payloadq = { + operation : "query", + query : queryStr + }; + + //create job + BulkJob queryJob = check baseClient->createQueryJob(payloadq); + int totalRecordsReceived = 0; + int totalIterationsOfGetResult = 0; + string[][]|error batchResult = []; + + //get batch result + foreach int currentRetry in 1 ..< maxIterations + 1 { + while true { + batchResult = baseClient->getQueryResult(queryJob.id, 5); + if batchResult is error || batchResult.length() == 0 { + break; + } else { + totalRecordsReceived += batchResult.length(); + totalIterationsOfGetResult += 1; + } + } + + if totalIterationsOfGetResult != 0 { + if totalRecordsReceived == 7 { + test:assertTrue(totalRecordsReceived == 7, msg = "Retrieving batch result failed."); + break; + } else { + if currentRetry != maxIterations { + log:printWarn("getBatchResult Operation Failed! Retrying..."); + runtime:sleep(delayInSecs); + } else { + log:printWarn("getBatchResult Operation Failed! Giving up after 5 tries."); + } + } + } else if batchResult is error { + if currentRetry != maxIterations { + log:printWarn("getBatchResult Operation Failed! Retrying..."); + runtime:sleep(delayInSecs); + } else { + log:printWarn("getBatchResult Operation Failed! Giving up after 5 tries."); + test:assertFail(msg = batchResult.message()); + } + } + } +} + + @test:Config { enable: true, dependsOn: [insertCsvFromFile, insertCsv, insertCsvStringArrayFromFile, insertCsvStreamFromFile] From 96f3846fb6fd46a206452b44b57957441f1f5e54 Mon Sep 17 00:00:00 2001 From: aashikam Date: Thu, 6 Jun 2024 20:50:08 +0530 Subject: [PATCH 09/12] Update test for maxRecords --- ballerina/tests/bulk_csv_query.bal | 1 + 1 file changed, 1 insertion(+) diff --git a/ballerina/tests/bulk_csv_query.bal b/ballerina/tests/bulk_csv_query.bal index 55b3033d..263a8a44 100644 --- a/ballerina/tests/bulk_csv_query.bal +++ b/ballerina/tests/bulk_csv_query.bal @@ -100,6 +100,7 @@ function queryCsvWithMaxRecords() returns error? { if totalIterationsOfGetResult != 0 { if totalRecordsReceived == 7 { test:assertTrue(totalRecordsReceived == 7, msg = "Retrieving batch result failed."); + test:assertTrue(totalIterationsOfGetResult == 2, msg = "Retrieving batch result failed."); break; } else { if currentRetry != maxIterations { From c9a5b8396bfdb0d28c7141317e7562cc5c11ab6d Mon Sep 17 00:00:00 2001 From: aashikam Date: Thu, 6 Jun 2024 21:09:45 +0530 Subject: [PATCH 10/12] Add changes from code review --- ballerina/client.bal | 6 ++- ballerina/tests/bulk_csv_query.bal | 60 +++++++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/ballerina/client.bal b/ballerina/client.bal index bdf255f2..62470d43 100644 --- a/ballerina/client.bal +++ b/ballerina/client.bal @@ -685,6 +685,7 @@ public isolated client class Client { return []; } batchingParams = string `results?locator=${locator}`; + path = utils:prepareUrl([API_BASE_PATH, JOBS, QUERY, bulkJobId, batchingParams]); } else { path = utils:prepareUrl([API_BASE_PATH, JOBS, QUERY, bulkJobId, RESULT]); } @@ -698,7 +699,10 @@ public isolated client class Client { return []; } lock { - self.sfLocators[bulkJobId] = check response.getHeader("sforce-locator"); + string|http:HeaderNotFoundError locatorValue = response.getHeader("sforce-locator"); + if locatorValue is string { + self.sfLocators[bulkJobId] = locatorValue; + } // header not found error ignored } string[][] result = check parseCsvString(textPayload); return result; diff --git a/ballerina/tests/bulk_csv_query.bal b/ballerina/tests/bulk_csv_query.bal index 263a8a44..1f4e2bbf 100644 --- a/ballerina/tests/bulk_csv_query.bal +++ b/ballerina/tests/bulk_csv_query.bal @@ -61,7 +61,6 @@ function queryCsv() returns error? { } } } - } @@ -69,7 +68,7 @@ function queryCsv() returns error? { enable: true, dependsOn: [insertCsvFromFile, insertCsv, insertCsvStringArrayFromFile, insertCsvStreamFromFile] } -function queryCsvWithMaxRecords() returns error? { +function queryWithLowerMaxRecordsValue() returns error? { runtime:sleep(delayInSecs); log:printInfo("baseClient -> queryCsv"); string queryStr = "SELECT Id, Name FROM Contact WHERE Title='Professor Level 02'"; @@ -123,6 +122,63 @@ function queryCsvWithMaxRecords() returns error? { } +@test:Config { + enable: true, + dependsOn: [insertCsvFromFile, insertCsv, insertCsvStringArrayFromFile, insertCsvStreamFromFile] +} +function queryWithHigherMaxRecordsValue() returns error? { + runtime:sleep(delayInSecs); + log:printInfo("baseClient -> queryCsv"); + string queryStr = "SELECT Id, Name FROM Contact WHERE Title='Professor Level 02'"; + + BulkCreatePayload payloadq = { + operation : "query", + query : queryStr + }; + + //create job + BulkJob queryJob = check baseClient->createQueryJob(payloadq); + int totalRecordsReceived = 0; + int totalIterationsOfGetResult = 0; + string[][]|error batchResult = []; + + //get batch result + foreach int currentRetry in 1 ..< maxIterations + 1 { + while true { + batchResult = baseClient->getQueryResult(queryJob.id, 10); + if batchResult is error || batchResult.length() == 0 { + break; + } else { + totalRecordsReceived += batchResult.length(); + totalIterationsOfGetResult += 1; + } + } + + if totalIterationsOfGetResult != 0 { + if totalRecordsReceived == 7 { + test:assertTrue(totalRecordsReceived == 7, msg = "Retrieving batch result failed."); + test:assertTrue(totalIterationsOfGetResult == 1, msg = "Retrieving batch result failed."); + break; + } else { + if currentRetry != maxIterations { + log:printWarn("getBatchResult Operation Failed! Retrying..."); + runtime:sleep(delayInSecs); + } else { + log:printWarn("getBatchResult Operation Failed! Giving up after 5 tries."); + } + } + } else if batchResult is error { + if currentRetry != maxIterations { + log:printWarn("getBatchResult Operation Failed! Retrying..."); + runtime:sleep(delayInSecs); + } else { + log:printWarn("getBatchResult Operation Failed! Giving up after 5 tries."); + test:assertFail(msg = batchResult.message()); + } + } + } +} + @test:Config { enable: true, dependsOn: [insertCsvFromFile, insertCsv, insertCsvStringArrayFromFile, insertCsvStreamFromFile] From 6e6de34cad571d8ab3481ad56799a88bf97fa6a2 Mon Sep 17 00:00:00 2001 From: Arshika Mohottige Date: Thu, 6 Jun 2024 21:37:36 +0530 Subject: [PATCH 11/12] Update ballerina/client.bal Co-authored-by: Nipuna Ransinghe --- ballerina/client.bal | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ballerina/client.bal b/ballerina/client.bal index 62470d43..07cb5776 100644 --- a/ballerina/client.bal +++ b/ballerina/client.bal @@ -657,8 +657,7 @@ public isolated client class Client { # + bulkJobId - Id of the bulk job # + maxRecords - The maximum number of records to retrieve per set of results for the query # + return - The resulting string[][] if successful else `error` - isolated remote function getQueryResult(string bulkJobId, int? maxRecords = ()) - returns string[][]|error { + isolated remote function getQueryResult(string bulkJobId, int? maxRecords = ()) returns string[][]|error { string path = ""; string batchingParams = ""; From 1f58aa8f41a226b5be8b487caedc0cb8cfe2a317 Mon Sep 17 00:00:00 2001 From: aashikam Date: Fri, 7 Jun 2024 06:39:37 +0530 Subject: [PATCH 12/12] Add changes from code review --- ballerina/tests/bulk_csv_query.bal | 2 -- 1 file changed, 2 deletions(-) diff --git a/ballerina/tests/bulk_csv_query.bal b/ballerina/tests/bulk_csv_query.bal index 1f4e2bbf..58db85a3 100644 --- a/ballerina/tests/bulk_csv_query.bal +++ b/ballerina/tests/bulk_csv_query.bal @@ -98,7 +98,6 @@ function queryWithLowerMaxRecordsValue() returns error? { if totalIterationsOfGetResult != 0 { if totalRecordsReceived == 7 { - test:assertTrue(totalRecordsReceived == 7, msg = "Retrieving batch result failed."); test:assertTrue(totalIterationsOfGetResult == 2, msg = "Retrieving batch result failed."); break; } else { @@ -156,7 +155,6 @@ function queryWithHigherMaxRecordsValue() returns error? { if totalIterationsOfGetResult != 0 { if totalRecordsReceived == 7 { - test:assertTrue(totalRecordsReceived == 7, msg = "Retrieving batch result failed."); test:assertTrue(totalIterationsOfGetResult == 1, msg = "Retrieving batch result failed."); break; } else {