Skip to content

Commit 533a216

Browse files
committed
fix(llmo): cap delivery-source name at CloudWatch 60-char limit (LLMO-5566)
Address MysticatBot non-blocking suggestions on PR #2680: - buildDeliverySourceName now hash-truncates names over 60 chars (CloudWatch Logs limit) using a deterministic sha256 suffix, so long IMS org / resource ids stay valid and the name remains stable across calls (idempotency depends on it) - document why deliveryId may be undefined after a ConflictException race (eventual consistency; delivery is enabled regardless, so no retry loop) Introduced by: #2680
1 parent 12983b0 commit 533a216

2 files changed

Lines changed: 32 additions & 1 deletion

File tree

src/support/cdn-log-delivery.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
* governing permissions and limitations under the License.
1111
*/
1212

13+
import crypto from 'crypto';
1314
import {
1415
CloudWatchLogsClient,
1516
PutDeliverySourceCommand,
@@ -77,14 +78,26 @@ export function buildDeliveryDestinationArn({
7778
return `arn:aws:logs:${region}:${adobeAccountId}:delivery-destination:${name}`;
7879
}
7980

81+
// CloudWatch Logs caps a delivery-source name at 60 characters.
82+
const MAX_DELIVERY_SOURCE_NAME_LENGTH = 60;
83+
8084
/** Per-resource delivery-source name, scoped by provider + org + resource. */
8185
export function buildDeliverySourceName({
8286
provider = DEFAULT_CDN_PROVIDER,
8387
imsOrgId,
8488
resourceId,
8589
}) {
8690
const { sourceNamePrefix } = getProviderConfig(provider);
87-
return `${sourceNamePrefix}-${toSafeAwsName(imsOrgId)}-${resourceId}`;
91+
const name = `${sourceNamePrefix}-${toSafeAwsName(imsOrgId)}-${resourceId}`;
92+
if (name.length <= MAX_DELIVERY_SOURCE_NAME_LENGTH) {
93+
return name;
94+
}
95+
// For unusually long org/resource ids, keep the readable head and append a deterministic hash
96+
// of the full name. Determinism matters: the name is regenerated on every call and idempotency
97+
// (GetDeliverySource) relies on it being byte-for-byte stable for the same inputs.
98+
const suffix = crypto.createHash('sha256').update(name).digest('hex').slice(0, 12);
99+
const head = name.slice(0, MAX_DELIVERY_SOURCE_NAME_LENGTH - suffix.length - 1);
100+
return `${head}-${suffix}`;
88101
}
89102

90103
/**
@@ -195,6 +208,10 @@ export async function createCdnLogDelivery(credentials, {
195208
// preserve the idempotency contract instead of surfacing a 500.
196209
if (err?.name === 'ConflictException' || err?.name === 'ResourceAlreadyExistsException') {
197210
const existing = await findExistingDelivery();
211+
// deliveryId may be undefined here if DescribeDeliveries hasn't caught up to the winning
212+
// CreateDelivery yet (eventual consistency). That is acceptable: delivery IS enabled — the
213+
// id is informational, and the caller already treats this as a successful no-op. We don't
214+
// retry-loop for the id since the idempotency outcome (alreadyExisted) is already correct.
198215
return {
199216
created: false,
200217
alreadyExisted: true,

test/support/cdn-log-delivery.test.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,20 @@ describe('cdn-log-delivery support', () => {
8484
expect(() => mod.buildDeliverySourceName({ provider: 'nope', imsOrgId: 'x', resourceId: 'y' }))
8585
.to.throw('Unsupported CDN provider');
8686
});
87+
88+
it('hashes-truncates to <=60 chars (deterministically) for long ids', () => {
89+
const imsOrgId = `${'A'.repeat(40)}@AdobeOrg`;
90+
const resourceId = 'E'.repeat(40);
91+
const name1 = mod.buildDeliverySourceName({ imsOrgId, resourceId });
92+
const name2 = mod.buildDeliverySourceName({ imsOrgId, resourceId });
93+
94+
expect(name1.length).to.equal(60);
95+
expect(name1).to.equal(name2); // deterministic — required for idempotency
96+
expect(name1).to.match(/^llmo-cf-/);
97+
// Different inputs must not collide on the truncated name.
98+
const other = mod.buildDeliverySourceName({ imsOrgId, resourceId: 'F'.repeat(40) });
99+
expect(other).to.not.equal(name1);
100+
});
87101
});
88102

89103
describe('createCdnLogDelivery', () => {

0 commit comments

Comments
 (0)