Race condition like behavior in Apollo Resolvers - apollo

We've been having some strange issues with field resolution using Apollo federation --
We have a type defined in Service A called ObjectA. We extended ObjectA in Service B by adding the localizedName field
ObjectA #key(fields: "id") {
id
name
localizedName #requires(fields: "id name")
}
Generally, everything works fine, however when we use a resolver from Service B which returns data in the form of
{
__typename: "ObjectB",
AList: [{__typename: "ObjectA", id: "someId" }],
... other ObjectB fields
}
Fields from ObjectA such as name are returned properly by the resolveReference function, however the localizedName field is usually, but not always null. When the field is null, we see the error
"message": "Field \"name\" was not found in response.",
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"stacktrace": [
"Error: Field \"name\" was not found in response.",
" at executeSelectionSet (C:\\Users\\user\\Documents\\workspace\\gateway\\node_modules\\#apollo\\gateway\\dist\\executeQueryPlan.js:230:27)",
When this possible race condition does not occur, the service works correctly and the localizedName field is resolved.
Is there something that I can do to resolve this? It seems to stem from the query plan trying to fetch the data from B for the field before the resolveReference has been called in A.

Related

Creating Batch Operations with AWS Amplify [GraphQL, DataStore, AppSync]

I've currently been handling batch operations with a for loop, but obviously, this is not the best approach, especially as I'm adding an 'upload by CSV' option, which will take 1000+ putItems.
I searched around for the best ways to implement this, specifically this link:
https://docs.aws.amazon.com/appsync/latest/devguide/tutorial-dynamodb-batch.html
However, even after following those steps mentioned I'm not able to achieve a batch operation. Below is my code for a 'batch delete' operation.
Here is my schema.graphql file:
type Client #model #auth(rules: [{ allow: owner }]) {
id: ID!
name: String!
company: String
phone: String
email: String
}
type Mutation {
batchDelete(ids: [ID]): [Client]
}
I then create two new files. One request mapping template and one response mapping template.
#set($clientsdata = [])
#foreach($item in ${ctx.args.clients})
$util.qr($clientsdata.delete($util.dynamodb.toMapValues($item)))
#end
{
"version" : "2018-05-29",
"operation" : "BatchDeleteItem",
"tables" : {
"Clients": $utils.toJson($clientsdata)
}
}
and then as per the tutorial a "simple pass through" response mapping template:
$util.toJson($ctx.result.data.Posts)
However now when I run the batchdelete command, I keep getting nothing returned.
Would really appreciate guidance on this!
When it comes to performing DynamoDB batch operations in tandem with Amplify, note that the table name specified in the schema is actually different per environment, i.e. your "Client" table wouldn't be recognized as "Clients" as you have stated it in the request mapping template, but rather the name it is given on Amplify push, per environment.
E.g. Client-<some alphanumeric number>-envName
Add the full name of the table to your request and response mapping templates.
Also your foreach statement should read:
#foreach($item in ${ctx.args.clientsdata}) wherein you iterate through each of the items in the array that is passed as the argument to the context object.
Hope this helps.

Dealing With Incoming Null Values In Cloud Data Fusion When Building Data Pipeline

I have started trying out google cloud data fusion as a prospect ETL tool that I can finally decide to use.When building a data pipeline to fetch data from a REST API source and load it to a MySQL database am facing this error Expected a string but was NULL at line 1 column 221'. Please check the system logs for more details. and yes it's true I have a field that is null from the JSON response am seeing
"systemanswertime": null
How do I deal with null values since the available dropdown in the cloud data fusion studio string is not working are they other optional data types that I can use?
Below are two screenshots showing my current data pipeline structure
geneneral view
view showing mapping and the output schema
Thank You!!
What you need to do is to tell HTTP plugin that you are expecting a null by checking the null checkbox in front of output on the right side. See below example
You might be getting this error because in the JSON schema you are defining the value properties. You should allow systemanswertime parameter to be NULL.
You could try to parse the JSON value as follow:
"systemanswertime": {
"type": [
"string",
"null"
]
}
In the case you don't have access to the JSON file, you could try to use this plug in in order to enable the HTTP to manage nulleable values by dynamically substituting the configurations that can be served by the HTTP Server. You will need access to the HTTP endpoint in order construct an accessible HTTP endpoint that can serve content similar to:
{
"name" : "output.schema", "type" : "schema", "value" :
[
{ "name" : "id", "type" : "int", "nullable" : true},
{ "name" : "first_name", "type" : "string", "nullable" : true},
{ "name" : "last_name", "type" : "string", "nullable" : true},
{ "name" : "email", "type" : "string", "nullable" : true},
]
},
In case you are facing an error such as: No matching schema found for union type: ["string","null"], you could try the following workaround. The root cause of this errors are when the entries in the response from the API doesn't have all the fields it needs to have. For example, some entries may have callerId, channel, last_channel, last data, etc... but others entries may have not have last_channel or whatever other field from the JSON. This leads to a mismatch in the schema provided in the HTTP source and the pipeline fails right away.
As pear this when nodes encounter null values, logical errors, or other sources of errors, you may use an error handler plugin to catch errors. The way is as following:
In the HTTP source plug-in, change the following:
Output schema to account for custom field.
JSON/XML field mapping to account into custom field.
Changed Non-HTTP Error Handling field to Send to Error. This way it pushes the records through error collector and the pipeline proceeds with subsequent records.
Added Error Collector and a sink to capture the error records.
With this method you will be able to run the pipeline and had the problematic fields detected.
Kind regards,
Manuel

GraphQL query - suppress non-null error and return partial data

I'm using AppSync and DynamoDB. Is there a way to suppress the non-null error and return partial data for a graphql query whose result omits a non-null field? For example if I run the following query:
query GetPerson {
getPerson(id: "123") {
name
active
}
}
And in my AppSync resolver I have logic that decides whether or not to return the value for active. If I decide not to return active, then I get the following response:
{
"data": {
"getPerson": null
},
"errors": [
{
"path": [
"getPerson",
"active"
],
"locations": null,
"message": "Cannot return null for non-nullable type: 'Boolean' within parent 'Person' (/getPerson/active)"
}
]
}
because in my schema the active field is non-null. Is there any to suppress this error and return the partial data (i.e. the value for name)? I would like to get a response like this instead:
{
"data": {
"getPerson": {
"name": "Jane Doe"
}
},
"errors": [
{
"path": [
"getPerson",
"active"
],
"locations": null,
"message": "Cannot return null for non-nullable type: 'Boolean' within parent 'Person' (/getPerson/active)"
}
]
}
No. A non-null field should never return null.
If the field is requested and it resolves to null, GraphQL will return an error. Because the field cannot be null, GraphQL will return null for the parent field instead. If that field is also non-null, it will return null for that field's parent... and so on, until it hits either a nullable parent field or the root (i.e. data). This behavior is described in the spec:
If an error is thrown while resolving a field, it should be treated as though the field returned null, and an error must be added to the "errors" list in the response.
If the result of resolving a field is null (either because the function to resolve the field returned null or because an error occurred), and that field is of a Non-Null type, then a field error is thrown. The error must be added to the "errors" list in the response...
Since Non-Null type fields cannot be null, field errors are propagated to be handled by the parent field. If the parent field may be null then it resolves to null, otherwise if it is a Non-Null type, the field error is further propagated to it’s parent field...
If all fields from the root of the request to the source of the field error return Non-Null types, then the "data" entry in the response should be null.
If it's possible for active to be null, then you should not make it non-nullable in your schema.

Intercept the Validation error from Flask restplus namespace class

Currently the Namespace parser validates the request arguments and throws error like
{
"errors": {
"file": "Missing required parameter in an uploaded file"
},
"message": "Input payload validation failed"
}
From the flask-app i want to intercept or handle these exceptions and send a customised response for consistency like
{
"errors": {
"file": "Missing required parameter in an uploaded file"
},
"message": "Input payload validation failed",
"id" : "some customer id "
}
Is it possible to handle this exception from app level instead of doing it for every api
According to this issue https://github.com/noirbizarre/flask-restplus/issues/530 there is a workaround to have a personalized message.
That said, it is possible to implement this with the definition of the BadRequest error handler and modify the data attribute:
#api.errorhandler(BadRequest)
def bad_request(self):
self.data.update({'id': 'some customer id'})
return {}, 400
Though, there is no clean way to avoid the empty dictionary return, as it is discarded.

How do I send an accessCode to a recipient and override the email using a template via the DocuSignAPI?

I have tried just about everything that I can think of and cannot get this to work.
I am trying to set an access code in my code and send it to a templateRole using the RequestSignatureFromTemplate call. Right now, all of my configuration info is in XML. I am NOT adverse to using JSON but not all of my developers know JSON.
Here is a snippet of my XML.
<envelopeDefinition xmlns=\"http://www.docusign.com/restapi\">
accountId>12345</accountId>
<status>sent</status>
<emailSubject>Test Form</emailSubject>
<emailBlurb>This is a template test.</emailBlurb>
<templateId>####-########</templateId>
<templateRoles>
<templateRole>
<accessCode>AccessCode124</accessCode>" +
<addAccessCodeToEmail>true</addAccessCodeToEmail>" +
<email>jevans#eclarifire.com</email>
<name>Test User</name>
<roleName>RoleOne</roleName>
<emailNotification>
<emailSubject>This is RoleOne's subject</emailSubject>
<emailBody>This is RoleOne's email.</emailBody>
<addAccessCodeToEmail>true</addAccessCodeToEmail>
</emailNotification>
</templateRole>
<templateRole>
<accessCode>AccessCode246</accessCode>
<email>jevans#eclarifire.com</email>
<name>Test User2</name>
<roleName>RoleTwo</roleName>
<emailNotification>
<emailBody>Your access code is 24680</emailBody>
</emailNotification>
</templateRole>
</templateRoles>
</envelopeDefinition>
You'll notice that I have two different implementations in the templateRole nodes. This is intentional since I'm trying everything that I can think of. In templateRole(1), I have added the addAccessCodeToEmail node in two different places and it doesn't work in either. I have also attempted to override the emailBlurb node in templateRole(1) and it doesn't work either.
I've been through the documentation and it says that you should be able to add anything that the Recipients format follows but I can't get it to work.
Any one got any ideas?
I've never used the addAccessCodeToEmail property in a "Create/Send Envelope" API request, because including the Access Code in the email that the recipient receives entirely nullifies the effect of using Access Code for authentication in the first place. i.e., the entire point of requiring the Recipient to enter an Access Code is to add another layer of assurance -- beyond the fact that someone merely has access to an email inbox -- before granting access to the envelope. If you're going to include the access code in the email that the Recipient receives, then using Access Code as the form of authentication isn't providing any additional security benefit whatsoever -- whoever has access to that email inbox will be able to easily access the envelope (same result as if you don't use Access Code at all).
That being said, there is a property that (for whatever reason) should allow you to have Access Code included in the email that the recipient receives -- I can't get this to work either. Maybe a bug, but someone at DocuSign will need to confirm. According to the documentation, this should result in the email containing the access code:
POST https://{{env}}.docusign.net/restapi/{{version}}/accounts/{{acctId}}/envelopes
{
"status" : "sent",
"emailBlurb" : "please sign",
"emailSubject" : "Please sign your document",
"templateId" : "TEMPLATE_ID",
"templateRoles" : [{
"name" : "John Doe",
"email" : "JohnsEmail#outlook.com",
"roleName" : "Signer1",
"accessCode" : "1234",
"addAccessCodeToEmail": "true"
}]
}
This request results in the recipient being required to enter an Access Code before he can access the Envelope, but the addAccessCodeToEmail property isn't having the expected effect, as the Access Code doesn't appear anywhere in the email that the recipient receives.
Alternative Approach (Best Practice):
Instead of adding the plain-text access code to the email, best practice when using the API to create/send an Envelope and require Access Code as the form of recipient authentication would be to do the following:
Programmatically set accessCode using a piece of data that your application knows about the recipient.
Set the "Email Blurb" (i.e., body of the email) to provide a hint as to the Access Code.
For example, let's say your application knows the Recipient's social security number. When you make the "Create Envelope" API request:
Set the value of accessCode to the last 4 digits of the Recipient's SSN.
Set the value of emailBlurb to include the messaging "Your access code is the last 4 digits of your SSN."
Doing things this way is much more secure than simply including the Access Code (in plain text) in the Email itself.
Finally, regarding your question about overriding the email subject & body for recipients -- see definition of emailNotification property on page 290-291 of the REST API guide (http://www.docusign.com/sites/default/files/REST_API_Guide_v2.pdf):
IMPORTANT: If this is enabled for one recipient, it overrides the Envelope Subject and EmailBlurb. Also, you must enable emailNotification for all recipients.
Sounds like you need to set emailNotification for each and every recipient if you want it to have any effect.
Here are a couple of examples that use "Composite Templates" in the Create Envelope API request to create an envelope with either ID Check or Phone Authentication as the method of recipient authentication.
Recipient Authentication = ID Check
POST https://{{env}}.docusign.net/restapi/{{version}}/accounts/{{acctId}}/envelopes
{
"emailSubject": "Please sign",
"emailBlurb": "Please sign...thanks!",
"status": "sent",
"compositeTemplates": [
{
"serverTemplates": [
{
"sequence" : 1,
"templateId": "TEMPLATE_ID"
}],
"inlineTemplates": [
{
"sequence" : 2,
"recipients": {
"signers" : [{
"email": "SallysEmail#outlook.com",
"name": "Sally Adamson",
"recipientId": "1",
"roleName": "ROLE_NAME",
"requireIdLookup": "true",
"idCheckConfigurationName": "ID Check $"
}]
}
}]
}]
}
Recipient Authentication = Phone Auth
POST https://{{env}}.docusign.net/restapi/{{version}}/accounts/{{acctId}}/envelopes
{
"emailSubject": "Please sign",
"emailBlurb": "Please sign...thanks!",
"status": "sent",
"compositeTemplates": [
{
"serverTemplates": [
{
"sequence" : 1,
"templateId": "TEMPLATE_ID"
}],
"inlineTemplates": [
{
"sequence" : 2,
"recipients": {
"signers" : [{
"email": "SallysEmail#outlook.com",
"name": "Sally Adamson",
"recipientId": "1",
"roleName": "ROLE_NAME",
"requireIdLookup": "true",
"idCheckConfigurationName": "Phone Auth $",
"phoneAuthentication": {
"recipMayProvideNumber": "false",
"senderProvidedNumbers": ["206-444-5555"]
}
}]
}
}]
}]
}