🐯

[AWS CDK tips]EventBridge (L2) で Content based filtering を記述する

2022/11/23に公開1

EventBridge の Rule や Archive で使える "EventPattern" を CDK の L2 Construct で記述する方法について小ネタを紹介します。

CDK version: v2.51.0

https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-patterns.html

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-events-rule.html

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-events-archive.html


結論

EventPattern の型定義を見て、「あれ、 "detail-type" 以外はオブジェクトで value の記述できないの・・・? Content filter 書けないじゃん」と思っていた人向けです(私です)

例えば source にプレフィックスを付けたい場合、

{
  "source": [ { "prefix": "my-app-events." } ]
}

CDK (for TypeScript) の L2 ではこのように書くことができます(Archive リソースの作成で例示)。

// import * as aws_events from 'aws-cdk-lib/aws-events';
// ...
// const eventBus = new aws_events.EventBus(this, 'Bus', {...});

// using prefix filter
new aws_events.Archive(this, 'Archive', {
  archiveName: `my-archive`,
  sourceEventBus: eventBus,
  eventPattern: {
    source: aws_events.Match.prefix('my-app-events.'),
  },
  retention: cdk.Duration.days(30),
});

// L1 での同等な実装
// eventPattern.source は any 型なので CloudFormation の定義通りのオブジェクト形式で記述可能
new aws_events.CfnArchive(this, 'Archive', {
  archiveName: `my-archive`,
  sourceArn: eventBus.eventBusArn,
  retentionDays: 30,
  eventPattern: {
    source: [
      { prefix: 'my-app-events.' },
    ],
  },
});

Match クラスのユーティリティが EventPattern の valeu 側に対応するstring[] 型の値を返します。これを使うことで L2 でもフィルタを記述可能です。

aws_events.Match.prefix('my-app-events.')  // => string[]

ほそく

EventPattern の記述として、"Content-based filtering" がサポートされています。

https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-patterns-content-based-filtering.html

例えば prefix を使った例では、アプリ独自仕様の source を "my-app-events" の名前空間で定義して、それを prefix でフィルタすることでアプリ用のイベントのみ Rule に転送したりアーカイブしたりといったことが可能です

{
  "source": [ { "prefix": "my-app-events." } ]
}

CDK の aws-events の L2, 例えば Rule を見てみると、"eventPattern" は EventPattern 型が指定されています。

https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_events.Rule.html#eventpattern

一方、EventPattern 型の定義を見てみると、 source は string[] 型になっていて、型定義上では prefix のようなフィルタは書けないように見えます。

// import * as aws_events from 'aws-cdk-lib/aws-events';
// ...
// const eventBus = new aws_events.EventBus(this, 'ResourceId', {...});

// ok
const rule1 = new aws_events.Rule(this, 'StoreRule', {
	eventBus: eventBus,
	eventPattern: {
		source: ['my-app-events.foo' ],
	},
});

// ng
const rule2 = new aws_events.Rule(this, 'StoreRule', {
	eventBus: eventBus,
	eventPattern: {
		// source は string[] 型
		source: [{
			prefix: 'my-app-events.',
		}],
	},
});

これを Match クラスのユーティリティを使って EventPattern 型の定義に則すように書けるよ、という話です(「結論」セクションにもどる)

Discussion

hassaku63hassaku63

できれば EventPattern は直感的に CFn 記法そのままのオブジェクトとして書きたいし、その書き方で型定義の恩恵を受けたい感じがしますね。

あんまり親切なインタフェースという感じはしませんが、かといって型定義に落とし込むのもそのテストを書くのも相当に面倒くさそうですね...。