Ross Coundon
05/23/2022, 9:07 PMError: 'some-stage-the-app-sst-coreFunctionsStack' depends on 'some-stage-the-app-sst-marketingStack' (some-stage-the-app-sst-coreFunctionsStack -> some-stage-the-app-sst-marketingStack/marketingBucket/Bucket/Resource.Arn). Adding this dependency (some-stage-the-app-sst-marketingStack -> some-stage-the-app-sst-coreFunctionsStack/resourcePhotoBucket/Bucket/Resource.Ref) would create a cyclic reference.
This implies to me that coreFunctionsStack imports, directly or indirectly, the marketingStack but it doesn’t. However, the opposite is true.
Then the second half of the error that seems to say that importing the resourcePhotoBucket into coreFunctionsStack is the problem but that doesn’t happen either. resourcePhotoBucket is created in coreFunctionsStack and isn’t used at all by marketing Stack.Adrian Schweizer
05/23/2022, 9:36 PMRoss Coundon
05/23/2022, 9:44 PMRoss Coundon
05/23/2022, 10:13 PMconst { resourcePhotoBucket } = sst.use(coreResourcesStack);
In the importing stack I can use the resourcePhotoBucket resource in permissions blocks for functions but as soon as I try to add a function as a notification, it causes the error I pasted above.
I.e. if I comment out the resourcePhotoBucket.addNotifications
block in the following code, it works. Uncomment, it breaks
const handleResizeUploadedPhoto = new sst.Function(ctx.stack, 'OmwResizeUploadedPhoto', {
handler: 'src/main/handler/resourceConfig/resourcePhotoHandler.handleResizeUploadedPhoto',
permissions: [primaryTable, resourcePhotoBucket],
environment: omwEnvironment,
});
console.log('bundled omwCreatePhoto');
resourcePhotoBucket.addNotifications(ctx.stack, {
photoCreated: {
type: 'function',
function: handleResizeUploadedPhoto,
events: ['object_created'],
},
});
Adrian Schweizer
05/23/2022, 10:35 PMRoss Coundon
05/23/2022, 10:41 PMuse()
) and attaches the permissions to it. I haven’t tested if this works yet but it does build.
The problem we have is related to a thread I was involved in the other day where we have various optional modules in our app. If those modules are purchased then some core modules need access to resources that the optional modules add to the application.
For example, we have a stats module, if and only if the customer purchases the marketing module we need to allow stats to access marketing tables.
This leads to a quite complex interdependent set of functional stacks. I think this is still simpler than the monolithic approach we were using before but quickly gets quite knotty. Unfortunately the error message wasn’t accurate in this case which meant chasing down a few dead ends before realising what the real problem wasAdrian Schweizer
05/23/2022, 10:44 PMAdrian Schweizer
05/23/2022, 10:44 PMFrank
// marketingStack
const { resourcePhotoBucket } = use(coreFunctionStack);
Doing this alone doesn’t add any inter stack dependency. The dependency is ONLY added when the resourcePhotoBucket
is being used. For example, when you do this:
// marketingStack
const { resourcePhotoBucket } = use(coreFunctionStack);
new Function(stack, "fn", {
...
permissions: [resourcePhotoBucket]
});
In this case, resourcePhotoBucket's ARN
is being used. Behind the scene:
• coreFunctionStack
exports the bucket’s ARN; and
• marketingStack
imports it
Hence the dependency is formed.Frank
coreFunctionsStack
references `marketingStack's marketingBucket's ARN`; and
• marketingStack
references coreFunctionStack's resourcePhotoBucket's ARN
Hence the cyclic reference.