binchoo / PaimonGanyu

여행 비서 페이몬! Genshin Impact AWS workflows & KakaoTalk chatbot skills
https://pf.kakao.com/_mtPFb
GNU General Public License v3.0
7 stars 1 forks source link

(awsutils) Define a DSL for event wrapper mappings. #3

Closed binchoo closed 2 years ago

binchoo commented 2 years ago

Customizing Event Wrapper Mappings

DSL definitions

Here defines the basic stucture of DSL that configures event wrapper mappings in YAML format. However, this is only to draw the conceptual structure in human-readable manner. The actual DSL is implemented by java objects.

DSL

WrappingManual:
  wrappingManual (required)

WrappingManual

mappingEntries

MappingEntries

- mappingEntry (required)
- mappingEntry (optional)
- ...

MappingEntry

Event: S3Event|SQSEvent|SNSEvent|DynamodbEvent| ... (required)
Condition: !Predicate (event)-> ... (optional)
WrapperSpec:
  wrapperSpec (required)

WrapperSpec

Wrapper: AwsEventWrapper<S3Event>| AwsEventWrapper<SQSEvent>| ... (required)
ConstructorArgs: (optional)
  - argType
  - argType
  - ...

An example

WrappingManual:
  - Event: SQSEvent
    WrapperSpec:
      Wrapper: SQSEventWrapper
  - Event: S3Event
    Condition: !Predicate (event)-> event.records.anyMatch(r-> r.s3.object.key.contains(".json"))
    WrapperSpec:
      Wrapper: S3EventObjectReader
      ConstructorArgs:
        - AmazonS3
binchoo commented 2 years ago

Java Implementation

manual // AwsEventWrapperManual
    .whenEvent(SQSEvent.class) // MappingEntry<SQSEvent>
        .wrapIn(SQSEventWrapper.class) // WrapperSpec<SQSEventWrapper>
    .and() // AwsEventWrapperManual
    .whenEvent(S3Event.class).satisfies(new IsJsonObject()) // MappingEntry<S3Event>
        .wrapIn(S3JsonObjectReader.class).argTypes(AmazonS3.class) // WrapperSpec<S3JsonObjectReader>
    .and() // AwsEventWrapperManual
    .whenEvent(S3Event.class)
        .wrapIn(S3ByteStreamReader.class).argTypes(AmazonS3.class)
    ;
binchoo commented 2 years ago

Is MappingEntry::Condition Property an Anti-Pattern?

Pros

  1. Reduces the number of deployed resources.

Cons

  1. If a lambda wants to avoid some specific events, I think they should be filtered before lambda invocation.
    • Subscription filters in CloudWatch Logs.
    • The prefix/suffix options in S3 Event Notification.
    • Add filtering lambdas before worker lambdas.
  2. If a lambda consumes two different types of events, it should be divided into two unidentical lambdas.
  3. If one Condition property has been set, there must be at least another additional property.
    • .satisfies(condition) always implies .satisfies(else-condition) is required.
  4. The additional load finding a matching condition may explode.
    e = the event type given to a lambda
    E = the size of the set of events
    N = the number of MappingEntry<e> in MappingEntries = O(C)
    avgload(e) = the average load to traverse MappingEntry<e> (Predicate logics decide this factor.)
    • Complexity = order of *O(E avgload(e))**
    • avgload(e) is so passive. A framework has no control over this kind of factor. I decide to remove MappingEntry::Condition that can lead users to bad decisions.