Skip to content

feat: simplify protobuf decoder registration #83

Description

@easyhooon

Summary

Add an optional registry/DSL that reduces the glue code required to connect an existing protobuf bridge to Dari.

This should improve ergonomics without replacing ProtobufPayloadDecoder, changing the application's wire format, or adding a protobuf runtime dependency to Dari core.

Motivation

The current protobuf API is intentionally runtime-agnostic, but applications must manually route every handler, direction, and payload part inside a decoder:

val decoder = ProtobufPayloadDecoder { bytes, context ->
    when (context.handlerName to context.part) {
        "createOrder" to REQUEST ->
            JsonFormat.printer().print(CreateOrderRequest.parseFrom(bytes))
        "createOrder" to RESPONSE ->
            JsonFormat.printer().print(CreateOrderResponse.parseFrom(bytes))
        else -> null
    }
}

This is manageable for a small bridge, but larger integrations may accumulate a large when block or duplicate an existing application-level protobuf registry. Users still need to map bridge request/response events to Dari, but decoder registration should require less Dari-specific convention.

Proposed Behavior

Provide a declarative, runtime-agnostic decoder registry. The consuming application should continue to own generated message types and display conversion:

val decoder = protobufDecoder {
    webToApp("createOrder") {
        request { bytes ->
            JsonFormat.printer().print(CreateOrderRequest.parseFrom(bytes))
        }
        response { bytes ->
            JsonFormat.printer().print(CreateOrderResponse.parseFrom(bytes))
        }
    }
}

val interceptor = Dari.createInterceptor(
    tag = "OrderBridge",
    protobufDecoder = decoder,
)

The exact API is open to refinement. A registry keyed by handlerName, MessageDirection, and PayloadPart is sufficient; Dari does not need to know the generated protobuf type.

Non-Goals

  • Do not replace the existing ProtobufPayloadDecoder API.
  • Do not require applications to change their .proto files, message fields, bridge transport, or request envelope.
  • Do not require Base64; callers continue to pass the original ByteArray received by their bridge.
  • Do not add a protobuf runtime dependency to dari-core or the default dari artifact.
  • Do not make the sample's protobufGreeting or StringValue structure a convention.

Design Considerations

  • Preserve direction-aware request and response registration.
  • Return the existing DECODER_UNAVAILABLE result for unmatched registrations.
  • Define deterministic behavior for duplicate keys, preferably failing fast during registry construction.
  • Keep decoding synchronous and document that conversion work must remain bounded.
  • Keep debug and no-op API compatibility.
  • Consider a separate optional runtime-specific adapter only if real usage justifies taking a protobuf dependency.

Effort Estimate

Estimated effort: 1–2 developer days.

  • Registry/DSL API and lookup behavior: 0.5 day
  • Tests for routing, unmatched handlers, and duplicate registrations: 0.5 day
  • Sample and English/Korean documentation updates: 0.5–1 day

Complexity is small to moderate. The capture, persistence, and detail pipelines do not need to change.

Acceptance Criteria

  • Consumers can register request and response decoders without writing a central context-matching when block.
  • Registrations distinguish handler, direction, and request/response part.
  • Existing ProtobufPayloadDecoder integrations continue to compile and behave unchanged.
  • Unknown handlers and decode failures retain the current safe fallback behavior.
  • The default artifacts remain protobuf-runtime-agnostic.
  • The sample and English/Korean documentation include a minimal registry example.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions