0

I am creating a webhook API and then passing the URL to a s3 Notification lambda but it creates a cyclic reference and I am not sure what is the problem and what should be an ideal solution.

Error

Error: 'webhookStack' depends on 's3EventStack' (webhookStack -> s3Stack/hls-audio-dist/Resource.DomainName, s3Stack -> s3EventStack/audio-bucket-event-handler/Resource.Arn). Adding this dependency (s3EventStack -> webhookStack/coconut-webhook-api/Resource.Ref) would create a cyclic reference.
    at S3EventStack._addAssemblyDependency

WebhookStack


    const webhookLambda = createLambdaHandler<WebhookLambdaProps>(
      this,
      "coconut-webhook",
      {
        path: "webhook/coconut-webhook",
        env: {
          cloudfrontURL: "holycow",
          wsDBTableName: wsDbTable.tableName,
          wsURL: wsStage.url,
          webhookSecret: webhookSecret,
        },
      }
    );

    this.webhookLambda = webhookLambda;

    webSocketApi.grantManageConnections(webhookLambda);

    const api = new LambdaRestApi(this, "coconut-webhook-api", {
      description: "webhook for coconut processing",
      proxy: false,
      deployOptions: {
        stageName: "dev",
      },
      handler: webhookLambda,
    });

    // set the webhook url to be used in s3
    // https://url.amz.com/notify?secret=123
    this.webhookURL = `${api.url}notify`;


Everything stays fine until I use the env in lambda

s3EventStack

    const bucketListenerLambda = createLambdaHandler<BucketUploadEventEnvProps>(
      this,
      "audio-bucket-event-handler",
      {
        path: "events/bucket-event",
        env: {
          // when passed it gives error
          webhookURL: props.webhookURL
        },
      }
    );

    // add listener on the bucket
    rawAudioBucket.addEventNotification(
      s3.EventType.OBJECT_CREATED,
      new s3n.LambdaDestination(bucketListenerLambda)
    );

    wsDbTable.grantWriteData(bucketListenerLambda);

stack

const cocoWebhook = new WebhookStack(app, "webhookStack", {
  wsDbTable,
});

const s3Stack = new S3Stack(app, "s3Stack", {
  wsDbTable,
  webhookLambda: cocoWebhook.webhookLambda,
  bucketNames: S3_BUCKET_NAMES,
});

const s3EventStack = new S3EventStack(app, "s3EventStack", {
  wsDbTable,
  webhookLambda: cocoWebhook.webhookLambda,
  webhookURL: cocoWebhook.webhookURL,
  rawAudioBucket: s3Stack.rawAudioBucket,
});

I am not an expert in this field, if anyone could explain whats going on here, it would be a great help.

Current workaround

  • Use SSM parameter store
Shivam
  • 652
  • 12
  • 14

1 Answers1

0

Cloudformation cyclical dependencies have two types:

  1. simple: a <-> b
  2. complex: a -> b -> c -> a

so options you have are (simplest to most complex):

  1. Split up the stacks such as create s3 before everything. This has the advantage of making your second stack more stable Items that are transient and might change or be deleted go in the second stack Items that persist data go in the first
  2. As you are doing push it into ssm and resolve it at runtime, this allows you to share between stacks as well
  3. Resolve it and resort to Cfn Resources such as work out the string of what the url is or use Ref to refer to the other resource. Nice if you have a existing CloudFormation example handy.
  4. Custom resources. By far the most complex as you are handling all CRUD states yourself. Gives you more control and is only really worth resorting to when there is no Cloudformation support but there is SDK support.

Another option is to ask AWS Support (see it in the AWS console.

As discussed here for more ideas.

lloyd
  • 1,683
  • 2
  • 19
  • 23
  • Putting s3 Stack on the top didn't resolve the issue :( – Shivam May 01 '22 at 13:51
  • where is the cyclical dependency? if it's s3 Notification lambda. move that one to another stack – lloyd May 02 '22 at 01:42
  • this is the error I am getting ` Error: 'webhookStack' depends on 's3EventStack' (webhookStack -> s3Stack/hls-audio-dist/Resource.DomainName, s3Stack -> s3EventStack/audio-bucket-event-handler/Resource.Arn). Adding this dependency (s3EventStack -> webhookStack/coconut-webhook-api/Resource.Ref) would create a cyclic reference. ` I am also creating a cloudfront distribution in webhook, the lambda creation is in 3rd step – Shivam May 02 '22 at 09:20