I am trying to create a CloudFormation for StepFunctions.
I would like to pass the DefinitionString as a parameter. The json string is pretty big . The max cap is 4096 bytes. How do i handle to such cases where parameter is more than the upper cap . Sample template is given below
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "An example template for a Step Functions state machine.",
"Resources" : {
"MyStateMachine" : {
"Type" : "AWS::StepFunctions::StateMachine",
"Properties" : {
"StateMachineName" : "HelloWorld-StateMachine",
"DefinitionString" : "{\"StartAt\": \"HelloWorld\", \"States\": {\"HelloWorld\": {\"Type\": \"Task\", \"Resource\": \"arn:aws:lambda:us-east-1:111122223333:function:HelloFunction\", \"End\": true}}}",
"RoleArn" : "arn:aws:iam::111122223333:role/service-role/StatesExecutionRole-us-east-1"
}
}
}
}
Related
I have a graphQL schema like this:
type Post {
id: String!
title: String!
content: String!
user: User!
}
type Query {
allPosts: [Post!]
singlePost(id: String!): Post!
}
type User {
name: String!
posts: [Post!]
}
The dynamo DataSource handles queries. In the query below, the user will be handled with a different resolver because it depends on different GSI.
query MyQuery {
allPosts {
content
title
user{
name
}
}
}
allPosts resolver looks like this:
{
"version" : "2017-02-28",
"operation" : "Query",
"query" : {
"expression" : "#t = :sk",
"expressionNames" : {
"#t": "type"
},
"expressionValues" : {
":sk": $util.dynamodb.toDynamoDBJson("post")
}
},
"index" : "GSI",
"select" : "ALL_ATTRIBUTES"
}
The resolver for user in the Post type is:
{
"version" : "2017-02-28",
"operation" : "Query",
"query" : {
"expression" : "PK = :pk AND SK = :sk",
"expressionValues" : {
":pk": "NEED TO ACCESS THE Partition KEY FROM ALL_POSTS",
":sk": $util.dynamodb.toDynamoDBJson("profile")
}
},
"select" : "ALL_ATTRIBUTES"
}
I need to access the partition key from the post object in each iteration to fetch the user of a specific id, just like the author resolver in this code (https://github.com/benawad/graphql-n-plus-one-example/blob/master/src/index.js):
const resolvers = {
Book: {
author: async parent => {
const author = await knex("users")
.select()
.where("id", parent.authorId)
.first();
return author;
}
},
Query: {
books: async () => {
const books = await knex("books")
.select()
.limit(10);
return books;
}
}
};
I've found the answer finally, the required object is stored in $ctx.source. All I had to do is to change the user resolver to this (Provided the result object have PK inside it):
{
"version" : "2017-02-28",
"operation" : "Query",
"query" : {
"expression" : "PK = :pk AND SK = :sk",
"expressionValues" : {
":pk": $util.dynamodb.toDynamoDBJson($ctx.source.PK),
":sk": $util.dynamodb.toDynamoDBJson("profile")
}
},
"select" : "ALL_ATTRIBUTES"
}
The $context.source references the parent object of the current field that’s being resolved. In this example, $ctx.source.PK refers to the individual Post object, which is then used for the query expression. ($context and $ctx are same). It works exactly like the parent argument in the apollo-server framework.
In AppSync i want to update item with array or stringset like this:
mutation addmeta{
addMetaDataOnPhoto(id:"xyz", metadata:["word1", "word2",...]){
metadata
}
}
this is how my mutation type looks:
type Mutatation{
addMetaDataOnPhoto(id: String!, metadata: [String]!): Photo
}
My question is how should look resolver for this mutation.
Thanks! :)
In order to update an attribute without replacing the entire item, you should use the UpdateItem DynamoDB operation.
In your example, if you want to replace the metadata array, your request mapping template shoud look like below:
{
"version" : "2017-02-28",
"operation" : "UpdateItem",
"key" : {
"id" : { "S" : "${context.arguments.id}" }
},
"update" : {
"expression" : "SET metadata = :vals",
"expressionValues": {
":vals" : $util.dynamodb.toDynamoDBJson($ctx.args.metadata)
}
}
}
Note: $util.dynamodb.toDynamoDBJson will convert your array into a DynamoDB typedValue. For more information and utilities see the AWS AppSync util reference.
I'm trying to get a record from a GSI and I'm stucked.
API Schema:
type DriverInfos {
id: String!
status: Int
lastLat: Float
lastLng: Float
idDriver: String # GSI
}
type Query {
getDriverInfosByDriver(idDriver: String): DriverInfos
}
Resolver :
{
"version" : "2017-02-28",
"operation" : "Query",
"index" : "idDriver-index",
"query" : {
## Provide a query expression. **
"expression": "#idDriver = :idDriver",
"expressionNames" : {
"#idDriver" : "idDriver"
},
"expressionValues" : {
":idDriver" : {
"S" : "${ctx.args.idDriver}"
}
}
}
}
Query :
query getDriverInfosByDriver{
getDriverInfosByDriver(idDriver: "1")
{
idDriver
status
lastLat
lastLng
}
}
Return :
{
"data": {
"getDriverInfosByDriver": {
"idDriver": null,
"status": null,
"lastLat": null,
"lastLng": null
}
}
}
GSI is well activated : Name : "idDriver-index" - PartitionKey : idDriver (String)
Try with other ids : 2, 3, ...
It seems that it comes from the resolver. I tried with different resolver but it always return an error.
Thank you in advance for your answers.
The issue is that a Query operation always returns a set of results not just one. If you want to leave your query type like this:
type Query {
getDriverInfosByDriver(idDriver: String): DriverInfos
}
then you should to change your response mapping template to this:
#if($ctx.result.items.size() > 0)
$util.toJson($ctx.result.items[0])
#else
null
#end
If instead the getDriverInfosByDriver query should return multiple info objects then you should change your schema to:
type DriverInfo {
id: String!
status: Int
lastLat: Float
lastLng: Float
idDriver: String # GSI
}
type DriverInfoConnection {
items: [DriverInfo]
nextToken:String
}
type Query {
getDriverInfosByDriver(idDriver: String): DriverInfoConnection
}
You can then leave your response mapping template as the default:
$util.toJson($ctx.result)
and then query it like so
query getDriverInfosByDriver{
getDriverInfosByDriver(idDriver: "1") {
items {
idDriver
status
lastLat
lastLng
}
}
}
I have a Cloud Formation template where I am looking to set an environment variable TAKE_ACTION on my API Gateway Stage with one of the endpoints of the stage, which requires the stage name, but when I access it using {"Ref":"MyApiStage"} I get a circular reference error.
Is there a workaround for what I'm trying to accomplish?
{
"AWSTemplateFormatVersion":"2010-09-09",
"Transform":"AWS::Serverless-2016-10-31",
"Description":"my POC.",
"Resources":{
"MyApiStage":{
"Type":"AWS::ApiGateway::Stage",
"Properties":{
"DeploymentId":{ "Ref":"ApiDeployment"},
"MethodSettings":[
{
"DataTraceEnabled":true,
"HttpMethod":"*",
"LoggingLevel":"INFO",
"ResourcePath":"/"
}
],
"RestApiId":{ "Ref":"MyApi" },
"StageName":"Prod",
"Variables":{
"TAKE_ACTION" : {"Fn::Join" :
["",
["https://",
{"Ref" : "ApiDeployment"},
".execute-api.",
{"Ref":"AWS::Region"},
".amazonaws.com/",
{"Ref":"MyApiStage"}
] ] }
}
}
}
}
}
Is it possible to link multiple documents in one view.
Eg :
{
"_id" : "0b86008d8490abf0b7e4f15f0c6a463b",
"name" : "copenhagen"}
{
"_id" : "8986008d8490abf0b7e4f15f0c6a333b",
"player" : "Mark"
}
{
"_id" : "4b86008d8490abf0b7e4f15f0c6a463c",
"location" : { "uuid" : "0b86008d8490abf0b7e4f15f0c6a463b"},
"player" : { "uuid" : "8986008d8490abf0b7e4f15f0c6a333b"},
"session" : "9876"
}
I want a view to include location document as well as the player document.
View :
"fetchByLocationAndPlayer": {
"map": "function(doc) { if (doc.session) { emit(doc.session, { _id : **doc.location.uuid** }); } }"
}
In the query I use includedocs = true.
How do I emit multiple documents corresponding to multiple keys in one document?
Yes it is possible. Just use two emits instead of one
emit(doc.session, {_id:doc.location.uuid});
emit(doc.session,{_id:doc.player.uuid});
Couch db wiki lists yet another way of doing this by iterating over the array and emitting linked docs one by one.