# ADR-0111: E27 Request Concurrency and Backpressure (Single In-Flight Policy)

Status: Accepted

## Context

The Elk E27 panel has a limited internal packet pool that is shared across:
- up to eight simultaneous client sessions
- a cloud connection
- internal panel operations

While the panel can accept outbound requests at high speed, queuing multiple
outstanding requests causes the panel to queue responses internally, which can
rapidly exhaust the packet pool and lead to degraded behavior or dropped
responses.

Guidance from the Elk Chief Engineer indicates the preferred operating model is:
- one request at a time per session
- send the next request immediately after the previous response is received

This constraint is architectural and must be enforced consistently to avoid
accidental misuse by higher layers.

## Decision

The E27 client and integration will enforce a strict
single in-flight request policy per session.

1. At most one request may be outstanding on a given session at any time.

2. Additional requests are queued locally and sent immediately when the
   response to the current request is received and processed.

3. Requests must not be sent in parallel, even if they are logically
   independent or originate from different higher-level callers.

4. This policy applies to all request types, including:
   - configuration and inventory downloads
   - status queries
   - control and automation commands

5. The library is responsible for enforcing this policy so that higher layers
   (e.g., Home Assistant entities or services) cannot accidentally violate it.

## Rationale

This approach:
- protects the panel’s limited packet pool
- prevents starvation of other sessions and the cloud connection
- provides near-optimal throughput on a LAN when requests are pipelined
  one-after-another
- avoids subtle failures caused by internal response queue exhaustion

Serializing requests at the client layer is simpler and safer than relying on
callers to coordinate concurrency correctly.

## Consequences

- The E27 library must implement an internal request queue with exactly one
  active request at a time per session.
- Callers may enqueue requests freely, but must not assume immediate
  transmission.
- Configuration downloads must be designed as sequential pipelines, not
  fan-out or parallel fetches.
- Home Assistant entities must never issue independent parallel refreshes; all
  outbound traffic flows through the shared queue.

## Scope / Non-Goals

- Does not define the internal data structure of the request queue.
- Does not define timeouts or retry policies for individual requests.
- Does not limit concurrency across multiple independent panels or sessions.

## References

- Elk E27 engineering guidance on packet pool limitations
- ADR-0012: Stable Inventory-Driven E27 API Surface
- ADR-0105: E27 Error Classification and Responsibility Boundaries
- ADR-0109: Home Assistant Integration Adapts to E27 Library Model

Addendum to ADR-0111: Single In-Flight Request with Timeout-Based Release

Status: Accepted (Addendum)

Context
-------
ADR-0111 establishes a strict single in-flight request policy to protect the
E27 panel’s limited packet pool and ensure correct request/response pacing.

During implementation, it is necessary to clarify how the system must behave
if a response is never received for an in-flight request, so that outbound
processing does not deadlock.

Decision
--------
The single in-flight request policy is augmented with an explicit
timeout-based release mechanism.

1. At most one request that expects a response may be in flight at any time.

2. An in-flight request is considered complete when one of the following
   occurs:
   a) A matching response is received and successfully resolved.
   b) The request times out and is failed locally.
   c) The request is failed due to connection loss or explicit abort.

3. Upon completion of an in-flight request (success or failure), the outbound
   queue is immediately released to allow the next queued request to be sent.

4. Time-based throttling (min interval / burst limits) continues to apply to
   all outbound sends as a pacing mechanism, but it must not override the
   single in-flight rule.

5. Time-based throttling must never advance the outbound queue while a request
   remains in flight. Only request completion (success or failure) may do so.

6. If a response arrives after the request has already timed out and been
   failed:
   - the response is treated as unexpected or unsolicited
   - it must not release the outbound queue
   - it must not resurrect or modify the failed request state

Rationale
---------
This addendum ensures:
- strict adherence to the panel’s “one request, one response” guidance
- no risk of exhausting the panel’s response packet pool
- forward progress even in the presence of lost or delayed responses
- clear separation between pacing (throttle) and correctness (request timeout)

By defining request completion as the sole release condition, the system
remains both safe and responsive.

Consequences
------------
- Each outbound request that expects a response must have an associated
  timeout.
- Timeout and failure paths must release the in-flight gate exactly once.
- Late responses are safely ignored and do not affect pacing.
- The outbound throttle remains a secondary safety, not a correctness
  mechanism.

References
----------
- ADR-0111: E27 Request Concurrency and Backpressure
- ADR-0112: E27 Bootstrap and Configuration Download Sequencing
- Vendor guidance on E27 packet pool limitations
