Chainlink async bridge task returns HTTP Error 422 - blockchain

I have to integrate my Chainlink Bridge task with an asynchronous call. Looking at the official documentation, there's the parameter named async and I can set it to true to invoke it asynchronously.
I also found this link which explains how to create Asynchronous callbacks.
I created the following job step:
fetch [type="bridge"
name="generate-hash"
requestData="{\\"id\\": $(jobSpec.externalJobID), \\"data\\": {\\"fileList\\": $(decode_cbor.fileList)}}"
async=true
]
I also set the environment variable BRIDGE_RESPONSE_URL equals to my Chainlink Oracle address. Looking at the documentation, I must set when using async external adapters.
If I start the job execution, I can see the async call to my bridge and it contains the responseURL equals to {BRIDGE_RESPONSE_URL}/v2/resume/{id}.
Once the process finishes, I call the responseURL using the PATCH http method with the following body:
{
"data": {
"fileList": ["aaa...fff", "bbbb...vvvv"],
"hashList": ["0x...", "0x..."]
}
}
The error I get is 422 - Unprocessable Entity.
What am I doing wrong?

I finally fixed the problem looking at the DEBUG logs on the Chainlink Node. My logs were these ones:
2023-01-17T21:49:01.538Z [DEBUG] PATCH /v2/resume/b5c2254d-6f85-4953-9f63-7911951a3fb4 web/router.go:535
body={"data":{"fileList":["aaa...fff","bbb...vvv"], hashList":["0x...","0x..."]}} clientIP={client_ip} ùerrors=Error #01: must provide only one of either 'value' or 'error' key
Even if the official Chainlink documentation says you have to send back the result or the error setting data or error, it's wrong.
You have to set the parameter value and then you can set the parameter data inside. This is how I updated my PATCH HTTP request body:
{
"value": {
"data": {
"fileList": ["aaa...fff", "bbbb...vvvv"],
"hashList": ["0x...", "0x..."]
}
}
}

Related

Setting JMSMessageID on stubbed jms endpoints in camel unit tests

I have a route that I am testing. I use stub://jms:queue:whatever to send/receive messages and extending CamelTestSupport for my test classes. I am having an issue with one of the routes that has a bean that uses an idempotent repo to store messages by "message id" for which it reads and stores the JMSMessageID property from exchange.
The problem I run into is that I can't figure out a way to set this property on messages sent on stubbed endpoints. Every time the method that requires this prop is called, the id returns null and i have to handle it as a null pointer. I can do this but the cleanest approach would be to just set the header on the test message. I tried includeSentJMSMessageId=true on endpoint, I tried using sendBodyAndHeader on producer and passing "JMSMessageID", "ID: whatever" in arguments, doesn't appear to work? I read that the driver/connectionfactory is supposed to set the header, but I'm not too familiar with how/where to do this. And since I am using a stubbed end points, I'm not creating any brokers/connectionfactories in my uts.
So dont stud out the JMS component replace it with a processor and then add the preferred JMSMessageID in the processor.
Something like this code:
#Test
void testIdempotency() throws Exception {
mockOut.expectedMinimumMessageCount(1);
//specify the route to test
AdviceWithRouteBuilder.adviceWith(context, "your-route-name", enrichRoute -> {
//replace the from with a end point we can call directly.
enrichRoute.replaceFromWith("direct:start");
//replace the jms endpoint with a processor so it can act as the JMS Endpoint.
enrichRoute.weaveById("jms:queue:whatever").replace().process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
//Set that ID to the one I want to test
exchange.getIn().setHeader("JMSMEssageID", "some-value-to-test");
}
});
// add an endpoint at the end to check if received a mesage
enrichRoute.weaveAddLast().to(mockOut);
});
context.start();
//send some message
Map<String,Object> sampleMsg = getSampleMessageAsHashMap("REQUEST.json");
//get the response
Map<String,Object> response = (Map<String,Object>)template.requestBody("direct:start", sampleMsg);
// you will need to check if the response is what you expected.
// Check the headers etc.
mockOut.assertIsSatisfied();
}
The JMSMessageID can only be set by the provider. It cannot be set by a client despite the fact that javax.jms.Message has setJMSMessageId(). As the JavaDoc states:
This method is for use by JMS providers only to set this field when a message is sent. This message cannot be used by clients to configure the message ID. This method is public to allow a JMS provider to set this field when sending a message whose implementation is not its own.

Error: 4 DEADLINE_EXCEEDED: Deadline Exceeded at Object.exports.createStatusError - GCP

I am trying to create a google cloud task from one of my Google Cloud Functions. This function gets triggered when a new object is added to one of my Cloud Storage buckets.
I followed the instructions given here to create my App Engine (App Engine Quickstart Guide)
Then in my Cloud Function, I added the following code to create a cloud task (as described here - Creating App Engine Tasks)
However, there is something wrong with my task or App Engine call (not sure what).
I am getting the following errors every now and then. Sometimes it works and sometimes it does not.
{ Error: 4 DEADLINE_EXCEEDED: Deadline Exceeded at Object.exports.createStatusError (/srv/node_modules/grpc/src/common.js:91:15) at Object.onReceiveStatus (/srv/node_modules/grpc/src/client_interceptors.js:1204:28) at InterceptingListener._callNext (/srv/node_modules/grpc/src/client_interceptors.js:568:42) at InterceptingListener.onReceiveStatus (/srv/node_modules/grpc/src/client_interceptors.js:618:8) at callback (/srv/node_modules/grpc/src/client_interceptors.js:845:24) code: 4, metadata: Metadata { _internal_repr: {} }, details: 'Deadline Exceeded' }
Do let me know if you need more information and I will add them to this question here.
I had the same problem with firestore, trying to write one doc at time; I solve it by returning the total promise. That is because cloud function needs to know when is convenient to terminate the function but if you do not return anything maybe cause this error.
My example:
data.forEach( d => {
reports.doc(_date).collection('data').doc(`${d.Id}`).set(d);
})
This was the problem with me, I was writing document 1 by 1 but I wasn't returning the promise. So I solve it doing this:
const _datarwt = [];
data.forEach( d => {
_datarwt.push( reports.doc(_date).collection('data').doc(`${d.Id}`).set(d) );
})
const _dataloaded = await Promise.all( _datarwt );
I save the returned promise in an array and await for all the promises. That solved it for me. Hope been helpful.

How to retrieve the current state of a running Step Functions in AWS

I'm giving the AWS' Step Functions a try and I'm interested in them for implementing long-running procedures. One functionality I would like to provide to my users is the possibility of showing execution's progress. Using describeExecution I can verify if some execution is still running or done. But progress is a logical measure and Step Functions itself has no way to tell me how much of the process is left.
For that, I need to provide the logic myself. I can measure the progress in the tasks of the state machine knowing the total number of steps needed to take and counting the number of steps already taken. I can store this information in the state of the machine which is passed among steps while the machine is running. But how can I extract this state using API? Of course, I can store this information is an external storage like DynamoDb but that's not very elegant!
The solution I have found my self (so far this is the only), is using getExecutionHistory API. This API returned a list of events that are generated for the Step Functions and it can include input or output (or neither) based on whether the event is for a starting a lambda function or is it for the time a lambda function has exited. You can call the API like this:
var params = {
executionArn: 'STRING_VALUE', /* required */
maxResults: 10,
reverseOrder: true
};
stepfunctions.getExecutionHistory(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
By reversing the order of the list of events, we can get the latest ones first. Then we can look for the latest output in the list. The first one you'll find will be the latest version of the output which is the current state of the Step Functions.

How to handle a 400 error with Ember Data (2.4.0-canary)

I can't figure out if my problem has to do with my query or my response or something else.
In my route I'm using a queryRecord:
model(params) {
return this.store.queryRecord('invitation', {
'invitation_token' : params.invitationToken
});
},
I'm properly receiving on the server side but I'm testing the case where the invitation token no longer exists. Therefore, the server is returning a 400 with a json payload which has an explanation of the error.
{"error":"Error finding invitation"}
But back on the ember side I'm just getting two errors (really it is just one).
Error while processing route: accept-invitation Ember Data Request GET /api/users/invitation returned a 400
Error: Ember Data Request GET /api/users/invitation returned a 400
It used to be (under Ember 2.2.1):
Error while processing route: accept-invitation Adapter operation failed Error: Adapter operation failed
Error: Adapter operation failed
What am I supposed to be returning from the server in the case that the token wasn't found? These messages makes it looks like something unexpected happen within Ember.
I'd assume that a 400 would tell Ember that there was an error, and it would go to the error state for the route. But instead it goes to the error state at the application level and spits out these error messages in the log.
I'm expecting the server to return a 400, so I'm not sure why Ember is complaining. What should I be returning and how should I properly handle this?
I believe that your application should be returning a response that is formatted differently. As per the JSON API specification,
Error objects MUST be returned as an array keyed by errors in the top
level of a JSON API document.
The specification also specifies that the following members, among others, may be provided (see the link for the full list).
title: a short, human-readable summary of the problem that SHOULD NOT
change from occurrence to occurrence of the problem, except for
purposes of localization.
detail: a human-readable explanation
specific to this occurrence of the problem. Like title, this field's
value can be localized
status: the HTTP status code applicable to this problem, expressed as
a string value.
If you try returning something along the lines of what is below, how does the tooling behave?
{
"errors": [
{
"status": "400",
"title": "Error finding invitation"
}
]
}

AWS Lambda "Process exited before completing request"

I am trying to call a DynamoDB client method and get one item from the DynamoDB table. I am using AWS Lambda. However, I keep getting the message:
"Process exited before completing request."
I have increased the timeout just to make sure, but the processing time is less than the timeout. Any advice?
console.log('Loading event');
var AWS = require('aws-sdk');
var dynamodb = new AWS.DynamoDB({apiVersion: '2012-08-10'});
exports.handler = function(event, context) {
dynamodb.listTables(function(err, data) {
});
var params = {
"TableName": "User",
"Key":
{"User Id" : {"S":event.objectId}
},
"AttributesToGet" : ["First Name","Last Name", "Latitude", "Longitude"],
"ConsistentRead" : true
}
dynamodb.getItem(params, function(response,result) {
response.on('data', function(chunk){
console.log(""+chunk);
console.log("test1")
context.done(result);
});
result.on('ready', function(data){
console.log("test2")
console.log("Error:" + data.error);
console.log("ConsumedCapacityUnits:" + data.ConsumedCapacityUnits);
context.done('Error',data);
// ...
});
});
};
Take a look at your memory consumption (included in last log line). I got the same message when I assigned too little memory to my lambda function.
The message "Process exited before completing request" means that the Javascript function exited before calling context.done (or context.succeed, etc.). Usually, this means that there is some error in your code.
I'm not a Javascript expert (at all) so there may be more elegant ways to find the error but my approach has been to put a bunch of console.log messages in my code, run it, and then look at the logs. I can usually zero in on the offending line and, if I look at it long enough, I can usually figure out my mistake.
I see you have some logging already. What are you seeing in the output?
I have used callback, instead of context.
More recent examples on aws website use callback instead of context.
To complete request, either of the below must be called:
callback(error); // This is used when there is an error
// or
callback(null, data); // This is used when there is a success
// 'data' will contain success result, like some JSON object
When lambda execution completes the request,
failing to call one of the above callbacks,
you will see below error:
"Process exited before completing request."
Error in your code. Remove the last }); and don't use context it is there for backward compatibility, use callbacks on node.js 4.3 and 6.1 runtime.
Maybe you are not following aws lamda standard of using the function
check this Golang code.
package main
import "github.com/aws/aws-lambda-go/lambda"
func main() {
lambda.Start(yourFunction)
}
func yourFunction(){
// do your stuff
}
Check your lamda memory usage, for me this error was occurred because of lambda was using 201 MB memory, which was greater than allowed 200 MB of memory for its execution.
First verify your code and if it is ok, increase memory allotment to this lambda from configuration > General Configuration > Edit > Increase memory