I'm currently using Aws Appsync, Aws Lambda, and Aws Neptune for an application. My Lambda function uses NodeJS 12. Right now my problem is getting back the appropriate JSON format from Neptune (more specifically gremlin) for my graphql api (appsync) when I do a mutation and eventually a query (I want to make sure the mutations are working first). For example:
When I run this test query to add a post, I get the following error with data being null: addPost test query and result
Does adding a vertex in gremlin return data/an object? If so, how do I get the appropriate JSON format for my appsync graphql api? I've been reading Practical Gremlin and searching the web but no luck. Thank you in advance.
AWS AppSync makes it easy to develop GraphQL APIs, which provides an access layer to the data and builds a flexible backend using AWS Lambda to connect to Neptune.
What is AWS AppSync? AppSync is a serverless GraphQL service. In simple terms, it's just an API gateway based on the GraphQL specification you can pay on-demand. GraphQL offers a friendly query language on top of HTTP, making it possible to fetch multiple different resources in one request, lowering network latency.
And thanks to AWS signatures this can happen in a secure way: AppSync can call the API as it can use an IAM Role with the necessary permissions, but for the public it's not available. In this article, we'll see how to configure AppSync to send a signed request to an API Gateway HTTP API using the HTTP data source.
SQL queries for highly connected data are complex and hard to tune for performance. Instead, Amazon Neptune allows you to use the popular graph query languages Apache TinkerPop Gremlin and W3C's SPARQL and openCypher to execute powerful queries that are easy to write and perform well on connected data.
More than likely what you're seeing is related to an incompatibility in Lambda with the default return format for the Node.js GLV. The default format returned is GraphSONV3, which is JSON-like but not well-formatted JSON. Lambda is expecting well-formatted JSON. You can change the mimetype when establishing your connection to Neptune to use GraphSONV2 which Lambda shouldn't have any issues with.
const dc = new DriverRemoteConnection(
`wss://<neptune-endpoint>:8182/gremlin`,
{ mimeType: "application/vnd.gremlin-v2.0+json" }
);
The other thing to validate is how you are resolving the promise being returned by the await'd Gremlin query. It looks like in your sample code that you are taking the result of the await'd query and feeding that into JSON.stringify(). I don't think that will work, as that will effectively return the JSON stringified version of the Promise (which is what you're seeing). What you can do in this case (if you want to submit queries asynchronously) is to take your Gremlin queries (or maybe even this larger case statement) and put it into an async function outside of the Lambda handler. Example:
const gremlin = require('gremlin');
const DriverRemoteConnection = gremlin.driver.DriverRemoteConnection;
const Graph = gremlin.structure.Graph;
const dc = new DriverRemoteConnection('wss://<neptune-endpoint>:8182/gremlin',
{ mimeType: "application/vnd.gremlin-v2.0+json" }
);
const graph = new Graph();
const g = graph.traversal().withRemote(dc);
async function callNeptune() {
const result = await g.addV('Post').property('userId','someid').
property('genre','somegenre').
property('caption','somecaption').
property('timestamp','sometimestamp').
toList();
console.log(result);
dc.close();
try {
return result;
} catch (error) {
return error;
}
}
exports.handler = async (event) => {
const rawOutput = await callNeptune();
const jsonOutput = JSON.stringify(rawOutput);
const response = {
statusCode: 200,
body: jsonOutput,
};
return response;
};
In this scenario, you're await'ing the async function with your Gremlin query via an await call that is now in the handler. So you can then take the results from that and feed it into JSON.Stringify() and return it. The Lambda service will resolve the promise of the handler at that point.
FWIW, there's little benefit to using async/await from a Lambda-backed API layer to Neptune. Both the Lambda function and the Neptune server side threads will be waiting (and holding up resources) until all of the promises are resolved. In many cases this can just add complexity over just using synchronous calls. It would be different if you were doing this from a long-running containerized application or from a web-based front end, where letting other processes in the meantime makes sense.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With