diff --git a/assets/error_codes.txt b/assets/error_codes.txt new file mode 100644 index 0000000..41d51f3 --- /dev/null +++ b/assets/error_codes.txt @@ -0,0 +1,95 @@ +const cooldownConflictError = 4000 +const waypointNoAccessError = 4001 +const tokenEmptyError = 4100 +const tokenMissingSubjectError = 4101 +const tokenInvalidSubjectError = 4102 +const missingTokenRequestError = 4103 +const invalidTokenRequestError = 4104 +const invalidTokenSubjectError = 4105 +const accountNotExistsError = 4106 +const agentNotExistsError = 4107 +const accountHasNoAgentError = 4108 +const registerAgentExistsError = 4109 +const registerAgentSymbolReservedError = 4110 +const registerAgentConflictSymbolError = 4111 +const navigateInTransitError = 4200 +const navigateInvalidDestinationError = 4201 +const navigateOutsideSystemError = 4202 +const navigateInsufficientFuelError = 4203 +const navigateSameDestinationError = 4204 +const shipExtractInvalidWaypointError = 4205 +const shipExtractPermissionError = 4206 +const shipJumpNoSystemError = 4207 +const shipJumpSameSystemError = 4208 +const shipJumpMissingModuleError = 4210 +const shipJumpNoValidWaypointError = 4211 +const shipJumpMissingAntimatterError = 4212 +const shipInTransitError = 4214 +const shipMissingSensorArraysError = 4215 +const purchaseShipCreditsError = 4216 +const shipCargoExceedsLimitError = 4217 +const shipCargoMissingError = 4218 +const shipCargoUnitCountError = 4219 +const shipSurveyVerificationError = 4220 +const shipSurveyExpirationError = 4221 +const shipSurveyWaypointTypeError = 4222 +const shipSurveyOrbitError = 4223 +const shipSurveyExhaustedError = 4224 +const shipRefuelDockedError = 4225 +const shipRefuelInvalidWaypointError = 4226 +const shipMissingMountsError = 4227 +const shipCargoFullError = 4228 +const shipJumpFromGateToGateError = 4229 +const waypointChartedError = 4230 +const shipTransferShipNotFound = 4231 +const shipTransferAgentConflict = 4232 +const shipTransferSameShipConflict = 4233 +const shipTransferLocationConflict = 4234 +const warpInsideSystemError = 4235 +const shipNotInOrbitError = 4236 +const shipInvalidRefineryGoodError = 4237 +const shipInvalidRefineryTypeError = 4238 +const shipMissingRefineryError = 4239 +const shipMissingSurveyorError = 4240 +const shipMissingWarpDriveError = 4241 +const shipMissingMineralProcessorError = 4242 +const shipMissingMiningLasersError = 4243 +const shipNotDockedError = 4244 +const purchaseShipNotPresentError = 4245 +const shipMountNoShipyardError = 4246 +const shipMissingMountError = 4247 +const shipMountInsufficientCreditsError = 4248 +const shipMissingPowerError = 4249 +const shipMissingSlotsError = 4250 +const shipMissingMountsError = 4251 +const shipMissingCrewError = 4252 +const shipExtractDestabilizedError = 4253 +const shipJumpInvalidOriginError = 4254 +const shipJumpInvalidWaypointError = 4255 +const shipJumpOriginUnderConstructionError = 4256 +const shipMissingGasProcessorError = 4257 +const shipMissingGasSiphonsError = 4258 +const shipSiphonInvalidWaypointError = 4259 +const shipSiphonPermissionError = 4260 +const waypointNoYieldError = 4261 +const shipJumpDestinationUnderConstructionError = 4262 +const acceptContractNotAuthorizedError = 4500 +const acceptContractConflictError = 4501 +const fulfillContractDeliveryError = 4502 +const contractDeadlineError = 4503 +const contractFulfilledError = 4504 +const contractNotAcceptedError = 4505 +const contractNotAuthorizedError = 4506 +const shipDeliverTermsError = 4508 +const shipDeliverFulfilledError = 4509 +const shipDeliverInvalidLocationError = 4510 +const existingContractError = 4511 +const marketTradeInsufficientCreditsError = 4600 +const marketTradeNoPurchaseError = 4601 +const marketTradeNotSoldError = 4602 +const marketNotFoundError = 4603 +const marketTradeUnitLimitError = 4604 +const waypointNoFactionError = 4700 +const constructionMaterialNotRequired = 4800 +const constructionMaterialFulfilled = 4801 +const shipConstructionInvalidLocationError = 4802 \ No newline at end of file diff --git a/assets/space-traders-sdk-authentication.png b/assets/space-traders-sdk-authentication.png new file mode 100644 index 0000000..9e2c7da Binary files /dev/null and b/assets/space-traders-sdk-authentication.png differ diff --git a/assets/space-traders-sdk-error-handling.png b/assets/space-traders-sdk-error-handling.png new file mode 100644 index 0000000..2410a92 Binary files /dev/null and b/assets/space-traders-sdk-error-handling.png differ diff --git a/assets/space-traders-sdk-retries.png b/assets/space-traders-sdk-retries.png new file mode 100644 index 0000000..828e774 Binary files /dev/null and b/assets/space-traders-sdk-retries.png differ diff --git a/sdk/README.md b/sdk/README.md index 5b24152..ac4bc77 100644 --- a/sdk/README.md +++ b/sdk/README.md @@ -59,6 +59,33 @@ By default, the connector read the token from the process variable with the name If you use a different variable for the token, or store the token as a connector secret, you need to adjust the authentication property of the connector. +![SDK property authentication](../assets/space-traders-sdk-authentication.png) + +### API Retries + +API calls can fail due to various reasons. One reason is that the SpaceTraders API is rate limited. It fails a call if +you send too many requests per second. + +The SDK allows to configure the number of retries and the delay between retries. + +By default, it retries the call 10 times with a delay of 1 second between retries. + +![SDK property retries](../assets/space-traders-sdk-retries.png) + +### API Error handling + +API calls can fail due to various reasons, for example, network issues or invalid parameters. + +The SDK allows to configure the error handling. A common use case is to throw a BPMN error if the call fails with a +specific error code (e.g. `4236`). The BPMN error can be caught by an error boundary event with the given +error code and handled in the process. + +By default, the SDK throws a BPMN error if the call returns a `400` status code. The BPMN error code is the name to the +SpaceTrader's error code (e.g. `shipNotInOrbitError` for the code `4236`). All error codes are listed +[here](https://docs.spacetraders.io/api-guide/response-errors/). + +![SDK property error handling](../assets/space-traders-sdk-error-handling.png) + ## Useful resources and tools Resources: diff --git a/sdk/spacetraders.json b/sdk/spacetraders.json index 6948a98..8b1e6a3 100644 --- a/sdk/spacetraders.json +++ b/sdk/spacetraders.json @@ -6,7 +6,7 @@ "icon": { "contents": "data:image/png;base64,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" }, - "version": 2, + "version": 3, "appliesTo": [ "bpmn:Task" ], @@ -30,6 +30,16 @@ "id": "responseMapping", "label": "Response Mapping" }, + { + "id": "error", + "label": "API Error handling", + "tooltip": "Handle error response codes from SpaceTrader's API in the process as BPMN error events." + }, + { + "id": "retries", + "label": "API Retries", + "tooltip": "Define retries if SpaceTrader's API returns an error response. Useful to handle API rate limiting." + }, { "id": "modificationWarning", "label": "Generated (DO NOT MODIFY)" @@ -6955,6 +6965,86 @@ "equals": "register" }, "optional": true + }, + { + "id": "customErrorHandling", + "label": "How to handle errors?", + "description": "By default, it maps the an error to a BPMN error event. The error code is the name of the SpaceTrader's error.", + "group": "error", + "binding": { + "type": "zeebe:property", + "name": "custom_error_handling" + }, + "type": "Dropdown", + "choices": [ + { + "name": "BPMN error by name (default)", + "value": "by_error_name" + }, + { + "name": "Custom", + "value": "custom" + } + ], + "value": "by_error_name" + }, + { + "id": "errorExpression", + "label": "Error expression", + "value": "={\n status: error.code,\n error_code: extract(error.message, \"\\d{4}\")[1],\n error_codes: {\n \"4000\":\"cooldownConflictError\",\n \"4001\":\"waypointNoAccessError\",\n \"4100\":\"tokenEmptyError\",\n \"4101\":\"tokenMissingSubjectError\",\n \"4102\":\"tokenInvalidSubjectError\",\n \"4103\":\"missingTokenRequestError\",\n \"4104\":\"invalidTokenRequestError\",\n \"4105\":\"invalidTokenSubjectError\",\n \"4106\":\"accountNotExistsError\",\n \"4107\":\"agentNotExistsError\",\n \"4108\":\"accountHasNoAgentError\",\n \"4109\":\"registerAgentExistsError\",\n \"4110\":\"registerAgentSymbolReservedError\",\n \"4111\":\"registerAgentConflictSymbolError\",\n \"4200\":\"navigateInTransitError\",\n \"4201\":\"navigateInvalidDestinationError\",\n \"4202\":\"navigateOutsideSystemError\",\n \"4203\":\"navigateInsufficientFuelError\",\n \"4204\":\"navigateSameDestinationError\",\n \"4205\":\"shipExtractInvalidWaypointError\",\n \"4206\":\"shipExtractPermissionError\",\n \"4207\":\"shipJumpNoSystemError\",\n \"4208\":\"shipJumpSameSystemError\",\n \"4210\":\"shipJumpMissingModuleError\",\n \"4211\":\"shipJumpNoValidWaypointError\",\n \"4212\":\"shipJumpMissingAntimatterError\",\n \"4214\":\"shipInTransitError\",\n \"4215\":\"shipMissingSensorArraysError\",\n \"4216\":\"purchaseShipCreditsError\",\n \"4217\":\"shipCargoExceedsLimitError\",\n \"4218\":\"shipCargoMissingError\",\n \"4219\":\"shipCargoUnitCountError\",\n \"4220\":\"shipSurveyVerificationError\",\n \"4221\":\"shipSurveyExpirationError\",\n \"4222\":\"shipSurveyWaypointTypeError\",\n \"4223\":\"shipSurveyOrbitError\",\n \"4224\":\"shipSurveyExhaustedError\",\n \"4225\":\"shipRefuelDockedError\",\n \"4226\":\"shipRefuelInvalidWaypointError\",\n \"4227\":\"shipMissingMountsError\",\n \"4228\":\"shipCargoFullError\",\n \"4229\":\"shipJumpFromGateToGateError\",\n \"4230\":\"waypointChartedError\",\n \"4231\":\"shipTransferShipNotFound\",\n \"4232\":\"shipTransferAgentConflict\",\n \"4233\":\"shipTransferSameShipConflict\",\n \"4234\":\"shipTransferLocationConflict\",\n \"4235\":\"warpInsideSystemError\",\n \"4236\":\"shipNotInOrbitError\",\n \"4237\":\"shipInvalidRefineryGoodError\",\n \"4238\":\"shipInvalidRefineryTypeError\",\n \"4239\":\"shipMissingRefineryError\",\n \"4240\":\"shipMissingSurveyorError\",\n \"4241\":\"shipMissingWarpDriveError\",\n \"4242\":\"shipMissingMineralProcessorError\",\n \"4243\":\"shipMissingMiningLasersError\",\n \"4244\":\"shipNotDockedError\",\n \"4245\":\"purchaseShipNotPresentError\",\n \"4246\":\"shipMountNoShipyardError\",\n \"4247\":\"shipMissingMountError\",\n \"4248\":\"shipMountInsufficientCreditsError\",\n \"4249\":\"shipMissingPowerError\",\n \"4250\":\"shipMissingSlotsError\",\n \"4251\":\"shipMissingMountsError\",\n \"4252\":\"shipMissingCrewError\",\n \"4253\":\"shipExtractDestabilizedError\",\n \"4254\":\"shipJumpInvalidOriginError\",\n \"4255\":\"shipJumpInvalidWaypointError\",\n \"4256\":\"shipJumpOriginUnderConstructionError\",\n \"4257\":\"shipMissingGasProcessorError\",\n \"4258\":\"shipMissingGasSiphonsError\",\n \"4259\":\"shipSiphonInvalidWaypointError\",\n \"4260\":\"shipSiphonPermissionError\",\n \"4261\":\"waypointNoYieldError\",\n \"4262\":\"shipJumpDestinationUnderConstructionError\",\n \"4500\":\"acceptContractNotAuthorizedError\",\n \"4501\":\"acceptContractConflictError\",\n \"4502\":\"fulfillContractDeliveryError\",\n \"4503\":\"contractDeadlineError\",\n \"4504\":\"contractFulfilledError\",\n \"4505\":\"contractNotAcceptedError\",\n \"4506\":\"contractNotAuthorizedError\",\n \"4508\":\"shipDeliverTermsError\",\n \"4509\":\"shipDeliverFulfilledError\",\n \"4510\":\"shipDeliverInvalidLocationError\",\n \"4511\":\"existingContractError\",\n \"4600\":\"marketTradeInsufficientCreditsError\",\n \"4601\":\"marketTradeNoPurchaseError\",\n \"4602\":\"marketTradeNotSoldError\",\n \"4603\":\"marketNotFoundError\",\n \"4604\":\"marketTradeUnitLimitError\",\n \"4700\":\"waypointNoFactionError\",\n \"4800\":\"constructionMaterialNotRequired\",\n \"4801\":\"constructionMaterialFulfilled\",\n \"4802\":\"shipConstructionInvalidLocationError\"\n },\n bpmn_error_code: get or else(get value(error_codes, error_code), error_code),\n bpmn_error_message: substring(extract(error.message, \"\\\"message\\\":\\\"(\\w|\\d|\\s|\\.|\\-)+\")[1], 12),\n result: \n if status = \"400\" \n then bpmnError(bpmn_error_code, bpmn_error_message)\n else null\n}.result", + "group": "error", + "binding": { + "key": "errorExpression", + "type": "zeebe:taskHeader" + }, + "type": "Hidden", + "condition": { + "property": "customErrorHandling", + "equals": "by_error_name" + } + }, + { + "id": "customErrorExpression", + "label": "Error expression", + "description": "Expression to handle errors. Details in the documentation.", + "value": "=if error.code = \"400\"\nthen bpmnError(\"error-1\", \"Something wrong.\")\nelse null", + "feel": "required", + "group": "error", + "binding": { + "key": "errorExpression", + "type": "zeebe:taskHeader" + }, + "type": "Text", + "condition": { + "property": "customErrorHandling", + "equals": "custom" + } + }, + { + "id": "retryCount", + "label": "Retries", + "description": "Number of retries", + "value": "10", + "feel": "optional", + "group": "retries", + "binding": { + "property": "retries", + "type": "zeebe:taskDefinition" + }, + "type": "String" + }, + { + "id": "retryBackoff", + "label": "Retry backoff", + "description": "ISO-8601 duration to wait between retries", + "value": "PT1S", + "feel": "optional", + "group": "retries", + "binding": { + "key": "retryBackoff", + "type": "zeebe:taskHeader" + }, + "type": "String" } ] } \ No newline at end of file