Can I see `sst.Cron` instances in AWS? I've got s...
# sst
a
Can I see
sst.Cron
instances in AWS? I've got some basic code and it doesnt seem to be working and I'm not sure how to debug it 🤔
Should they be in EventBridge > Rules ?
Is it because I'm only in local dev mode, not actually deployed yet?
Okay, I deployed (via the awesome SEED) and see this now:
Copy code
Template error: IAM role dev-ecologiApiV2-poc-ecol-srcservicesuserslistUser-KTAYWIITDMW0 doesn't exist
for my
Copy code
srcservicesuserslistUsersindexhandlerJob397ACCF4
call. Any ideas 🤔
Hm.. docs suggest it should work in local dev
s
what does your Cron definition look like?
a
Copy code
export const cron = (stack: sst.Stack): sst.Cron =>
  new sst.Cron(stack, path, {
    schedule: Duration.minutes(10),
    job: path,
  });
I have it located next to the lambda itself and then I'm doing
Copy code
[...userCrons].forEach((cron) => cron(this));
In the Stack constructor.
Oh snap.. is it a
this
scope issue? 🤦
s
don’t think so. is
path
just a string locating the src file?
a
yes
I swapped out for the
console.log('hi')
lambda + cron example from the docs and it worked...
s
I could be wrong, but I think that will wind up creating duplicate Lambda functions. I had that issue with API routes.. I had two different routes using the same Lambda, and it tried to create it twice. try creating the function first,
const myFunc = new sst.Function(…)
and then passing that to
job
a
Okay thanks 👍
r
We do it like this, define a Function then reference it in the Cron definition
Copy code
const someCron = new sst.Cron(this, 'TheCron', {
      schedule: 'rate(5 minutes)',
      job: {
        function: theFunction,
      },
    });
a
Thanks. Can you add functions like that in app sync?
Copy code
api.addResolvers(this, {
  "Query    listNotes": listNotesFunc,
  "Mutation createNote": "src/create.main",
});
r
Sorry, I'm not familiar with AppSync
a
also, string definitions don't need
this
in scope...
new Function
does 😕
Okay, so it seems there is an issue where there are indeed 2 lambda being created, but only one is getting the IAM policy 😞 I created a new
Cron
that isn't linked to an existing resolver handler and it works just fine 👌
s
@Alex Price yes, for resolvers you can do the same thing. looking at the TypeScript definition:
Copy code
readonly resolvers?: {
        [key: string]: string | FunctionDefinition | AppSyncApiResolverProps;
    };
you can pass a
FunctionDefinition
, which also includes an
sst.Function
a
Nice. It's still pretty ugly, having to pass the stack
this
ctx around 😕 Any better solutions?
s
unfortunately with SST & CDK, there’s a bit of dependency injection, yeah. just the way it is
someone else might have a better way though
f
hmm @Alex Price this looks right to me, did u manage to get it to work?
Copy code
export const cron = (stack: sst.Stack): sst.Cron =>
  new sst.Cron(stack, path, {
    schedule: Duration.minutes(10),
    job: path,
  });
s
@Frank wouldn’t using
path
(a string) create duplicate functions? I had issue with
sst.Api
so I had to create an
sst.Function
and pass that instead
f
Sorry, i mis-read the code, @Sam Hulick is right this shouldn’t work 😅
a
This does work.. but not when the handler is used else where (as a resolver for AppSync in case)
f
Does
someCron
only getting called once per stack?
a
In terms of code, it does now!
the Cron is the only construct which is using this handler which works nicely. I think thats fine for now
f
Right.. you will get an error when called more than once per stack as @Sam Hulick suggested, b/c you can’t have multiple cron jobs with the same name
Cron
in the same stack
Alright let’s move on 🤓 Can I see how you are defining the AppSync?
a
Yup!
Copy code
const api = new sst.AppSyncApi(this, 'Api', {
      graphqlApi: {
        schema: 'graphql/schema.graphql',
        xrayEnabled: true,
        authorizationConfig: {
          defaultAuthorization: {
            authorizationType: appsync.AuthorizationType.OIDC,
            openIdConnectConfig: {
              clientId: '',
              oidcProvider: '',
            },
          },
          additionalAuthorizationModes: [
            {
              authorizationType: appsync.AuthorizationType.API_KEY,
              apiKeyConfig: {
                expires: aws.Expiration.after(aws.Duration.days(7)),
              },
            },
          ],
        },
        logConfig: {
          excludeVerboseContent: false,
          fieldLogLevel: appsync.FieldLogLevel.ALL,
        },
      },
    });

    api.addResolvers(this, {
      ...fooLambda,
      ...barLambdas,
    });
Where fooLambdas looks like:
Copy code
export const fooLambdas = {
  'Query getFoo': getFooPath,
  'Mutation createFoo': createFooPath,
};
f
And what’s the error you are getting?
a
I'm not 😆
I was getting an error when i was trying to build a cron around one of the existing resolvers
but I can just not do that, so we're good 👍
Sorry for the confusion!
f
Oh gotcha.. my bad😁
s
@Alex Price be aware of your resource count if you have a stack with a lot of resolvers. for each resolver (the way you’re defining them), I believe it’ll create a single Lambda data source. you can create a handful of data sources elsewhere in the code (maybe separated by concern) and then point the resolvers to those, e.g.:
Copy code
resolvers: {
      'Mutation createEvent': 'trackingDS',
      'Mutation createSession': 'trackingDS',
      'Mutation updateTranscodeStatus': 'trackDS',
    },
(Frank can correct me if I’m wrong on that)
a
Thanks Sam! Yeah I believe there is guidance for splitting stacks out in the pipeline @Frank? in terms of docs*
f
Yeah, for example, this will create 2 data sources, 1 for each resolver:
Copy code
api.addResolvers(this, {
  'Query getFoo': 'src/foo.main',
  'Mutation createFoo': 'src/foo.main',
});
While this will create 1 data source, shared by both resolvers:
Copy code
api.addDataSources(this, {
  fooDS: 'src/foo.main',
});

api.addResolvers(this, {
  'Query getFoo': 'fooDS',
  'Mutation createFoo': 'fooDS',
});
a
Good to know. Our current set up is to have one handler per resolver, but I guess we'll hit the limits pretty fast. We could have seperate files for each resolver, and one DS which collates those into a single lambda 🤔