IAdapterPoolHub
Namespace: Meshmakers.Octo.Communication.Contracts.Hubs
Server-side hub interface of the adapter pool management channel at
/adapterPoolHub (AB#4924, concept Β§4).
public interface IAdapterPoolHub
Remarks:
π΄ A separate hub from , deliberately./{tenantId:tenantId}/adapterHub is tenant-addressed by construction and
AdapterHubAuthorizationFilter (AB#5063) exists precisely to bind such a connection
to its route tenant. A pool member belongs to no tenant β it is handed one per
lease β so it cannot use that route, and weakening that filter to let it would give away
the one check the adapter data plane has. The pool channel is mounted next to
/operatorHub with its own staged gate instead.
What the connection proves and what it does not. The connection is authorized
against the lending tenant's read-write policy (concept Β§8, Q4) and bound to that
tenant. It proves the member belongs to a pool that tenant owns. It proves nothing at all
about a borrower: the authority to act inside a borrowing tenant travels on
LeaseDto, as that tenant's own PipelineServiceAccount credential, and
expires with the lease.
Skew rule, as for AB#4917: controller, octo-sdk and the adapter SDK ship together,
and both directions degrade through the once-only HubException pattern so a rolling
upgrade window logs once instead of flooding.
Methodsβ
RegisterPoolMemberAsync(PoolMemberRegistrationDto)β
Registers the calling process as a member of an adapter pool, making it eligible for leases.
Task<PoolMemberRegistrationResultDto> RegisterPoolMemberAsync(PoolMemberRegistrationDto registration)
Parametersβ
registration PoolMemberRegistrationDto
Returnsβ
Task<PoolMemberRegistrationResultDto>
Remarks:
The declared PoolMemberRegistrationDto.AdapterPoolTenantId is checked against the
tenant the connection's token was issued for. Under the gate's Enforce mode a
mismatch β or a connection with no tenant at all β is refused with a HubException;
under LogOnly it is logged and allowed, exactly like the other two hub gates, so the
mode can be armed per environment without a release.
ResumePoolMemberAsync(PoolMemberRegistrationDto)β
Registers the calling process as a member of an adapter pool while it is still running a lease (AB#5826) β after a reconnect, typically because the controller process restarted or the connection dropped mid-lease.
Task<PoolMemberRegistrationResultDto> ResumePoolMemberAsync(PoolMemberRegistrationDto registration)
Parametersβ
registration PoolMemberRegistrationDto
Returnsβ
Task<PoolMemberRegistrationResultDto>
Remarks:
Same checks as IAdapterPoolHub.RegisterPoolMemberAsync(PoolMemberRegistrationDto). In addition the controller looks at PoolMemberRegistrationDto.ActiveLease: when the persisted execution proves the lease belongs to this member of this pool and is still running, the controller adopts it β the member is recorded as busy with that lease, nothing is re-queued, and the member's release completes the execution as if no reconnect had happened. When it cannot (the execution has moved on), the member is still recorded as busy until its release, so no second lease lands on a process that has to refuse it.
π΄ A separate method rather than a field on the registration, on purpose. A
controller that pre-dates it answers with a HubException ("unknown hub method"),
and the member then defers its registration until the lease is released β the
behaviour before AB#5826. Announcing the lease on IAdapterPoolHub.RegisterPoolMemberAsync(PoolMemberRegistrationDto)
would have made such a controller offer the busy member as free.
The default implementation reports the method as unsupported, which is exactly what an older controller does on the wire; it keeps hand-written test doubles compiling.
ReleaseLeaseAsync(LeaseResultDto)β
Hands a lease back after the work item is done (concept Β§4).
Task ReleaseLeaseAsync(LeaseResultDto result)
Parametersβ
result LeaseResultDto
Returnsβ
Remarks:
π΄ Called after the member has already dropped everything tenant-scoped β the message reports the release, it does not cause it. A release naming a lease the controller no longer holds is never applied to the member's current lease.
Since AB#5826 such a release is not simply dropped either: a lease this controller instance does not hold any more (it restarted, or the member reconnected) is matched by its id against the leases of disconnected members, and otherwise against the persisted execution named by LeaseResultDto.ExecutionId β applied only when that execution was leased to LeaseResultDto.MemberId and is still running.
HeartbeatAsync(PoolMemberHeartbeatDto)β
Reports that the member β and the lease it holds, if any β is still alive.
Task HeartbeatAsync(PoolMemberHeartbeatDto heartbeat)
Parametersβ
heartbeat PoolMemberHeartbeatDto
Returnsβ
Remarks:
A SignalR connection can stay up while the process behind it is wedged. This is what lets the controller tell a long work item from a dead member without waiting for the transport, and it is the input to concept Β§6's "release never arrives" row.