Skip to content

[P1] QuotaHandle (AutoCloseable) + A2A operation classification #5362

Description

@qqeasonchen

Tracking sub-issue of #5354. Part of the production-HA acceptance plan (Phase 2, P1).

What this PR changes

Quota accounting gets a release-handle (AutoCloseable) and the gate learns the A2A operation taxonomy. The handler is paired with a try-with-resources block at every call site, so disconnect / cancel / timeout automatically releases the quota slot.

QuotaHandle API

public final class QuotaHandle implements AutoCloseable {
    private final QuotaManager manager;
    private final String quotaKey;
    private final QuotaManager.Resource resource;
    private final long units;
    private boolean closed;
    @Override public void close() {
        if (!closed) { manager.release(quotaKey, resource, units); closed = true; }
    }
}

SecurityGate.acquire(RequestContext ctx, Operation op, long units) throws QuotaExceededException returns the handle; the call site uses try (QuotaHandle h = gate.acquire(...)) { ... }. Every existing quotaManager.tryAcquire(...) call site in UniIngressService, UniHttpServer, A2AGatewayHttpHandler, UniAdminServer, and the connector scheduler is converted to the handle form.

A2A operation classification

RequestContext.Operation gains A2A_SUBMIT, A2A_GET, A2A_LIST, A2A_STREAM, A2A_WAIT, A2A_CANCEL. The gate maps them to distinct QuotaManager.Resource buckets:

Operation Resource Reason
A2A_SUBMIT THROUGHPUT rate-limited like publish
A2A_GET / A2A_LIST THROUGHPUT light read traffic
A2A_STREAM CONNECTIONS one slot per active SSE/WS
A2A_WAIT BACKLOG one slot per pending wait

A2AGatewayHttpHandler builds a distinct RequestContext per operation; the existing single-context-for-all-handlers pattern is split.

Acceptance criteria

  • QuotaHandle is added with *_check test that asserts close() calls release exactly once.
  • SecurityGateQuotaHandleTest covers: (a) successful acquire + close releases the slot, (b) acquire throws QuotaExceededException without consuming, (c) double-close is a no-op, (d) A2A_STREAM CONNECTIONS slot is released on SSE disconnect.
  • arch-guard test ruleQuotaRequiresHandle (from [P0] arch-guard: ban raw QuotaManager calls (force release-handle) #5358) is tightened: raw tryAcquire outside the handle class now fails the build.
  • RouteLevelQuotaTest exercises HTTP publish / A2A submit / A2A stream / legacy TCP / SSE / admin routes end-to-end and asserts the right Resource is charged per route.

Verification

./gradlew :eventmesh-runtime:test --tests "*QuotaHandleTest*"
./gradlew :eventmesh-runtime:test --tests "*SecurityGateQuotaHandleTest*"
./gradlew :eventmesh-runtime:test --tests "*RouteLevelQuotaTest*"

Depends on / blocks

References

  • eventmesh-runtime/src/main/java/org/apache/eventmesh/runtime/security/gate/QuotaManager.java
  • eventmesh-runtime/src/main/java/org/apache/eventmesh/runtime/security/gate/SecurityGate.java
  • eventmesh-runtime/src/main/java/org/apache/eventmesh/runtime/security/gate/RequestContext.java
  • eventmesh-runtime/src/main/java/org/apache/eventmesh/runtime/a2a/A2AGatewayHttpHandler.java

Part of the production-HA topology in #5354. See also #5352 and #5353.

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

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions