You are implementing a simplified connection router / load balancer for a Jupyter-like multi-tenant server system.
There are N target servers, indexed from 0 to N - 1.
Each target server can maintain at most maxConnectionsPerTarget concurrent connections.
You will implement a small, stateful simulator that processes a sequence of commands and updates internal state accordingly.
Assume all commands are processed sequentially in a single thread.
Connection IDs (connId) are arbitrary identifiers (e.g., strings or integers) and are unique per logical client connection.
Design an API like the following (you can adapt naming / exact signatures to your chosen language):
You must support the following behavior, built up in five parts.
Implement connect(connId) for the basic case (ignore duplicates, DISCONNECT, and SHUTDOWN for now).
[0, 1, ..., N-1]
.
connect(connId)
is called for a
new
connId
:
N
).
targetIndex
.
For now, it is acceptable to assume all connections are unique and never disconnected. You should still design your internal data structures anticipating later parts.
Extend connect(connId) to handle duplicate connections with the same connId:
connId
is
already connected
to some target:
connId
.
connId
is not currently connected should you perform a new assignment using the Part 1 logic.
You will therefore need to maintain a mapping from connId to its current targetIndex.
Implement disconnect(connId) to explicitly close a connection:
connId
is currently connected to some target:
connId
.
true
.
connId
is
not
currently connected (unknown or already disconnected):
false
.
The round-robin pointer is not affected by disconnect operations.
Now fully enforce per-target capacity via the constructor parameter maxConnectionsPerTarget.
maxConnectionsPerTarget
active connections at any time.
connect(connId)
for a previously unseen
connId
:
N
).
targetIndex
.
-1
to indicate that no target could be assigned.
Duplicate connect(connId) calls (where connId is already connected) still behave as in Part 2: return the existing target and do not change state.
Implement shutdown(targetIndex) to temporarily take a target offline and evict all connections currently on that target.
shutdown(targetIndex)
is called:
connect
operations.
connIds currently assigned to this target
.
connId
:
connId → targetIndex
.
connId
s.
connect
calls occurred (i.e., connection creation time order on that target).
connect
calls (treated as unavailable), regardless of its current connection count.
disconnect(connId)
should still behave correctly even if the connection was already evicted by a shutdown (i.e., just return
false
when
connId
is not found).
You may assume that targets, once shut down, never come back up in this problem variant.
Q
be the number of operations (CONNECT / DISCONNECT / SHUTDOWN) and
N
be the number of targets.
connId
to
targetIndex
.
Implement the full ConnectionRouter with correct behavior across all five parts.