message: Idle "write" client keeps submitting summaries after being removed from quorum (Nack: nonexistent client)
  Closes
diff: @@ -147,9 +147,6 @@ export class ConnectionManager implements IConnectionManager {
  /** True if there is pending (async) reconnection from "read" to "write" */
  private pendingReconnect = false;
  - /** downgrade "write" connection to "read" */
  - private downgradedConnection = false;
  -
  private clientSequenceNumber = 0;
  private clientSequenceNumberObserved = 0;
  /** Counts the number of noops sent by the client which may not be acked. */
  @@ -176,12 +173,7 @@ export class ConnectionManager implements IConnectionManager {
  * The current connection mode, initially read.
  */
  public get connectionMode(): ConnectionMode {
  - assert(!this.downgradedConnection || this.connection?.mode === "write",
  - 0x277 /* "Did we forget to reset downgradedConnection on new connection?" */);
  - if (this.connection === undefined) {
  - return "read";
  - }
  - return this.connection.mode;
  + return this.connection?.mode ?? "read";
  }
  public get connected() { return this.connection !== undefined; }
  @@ -548,7 +540,6 @@ export class ConnectionManager implements IConnectionManager {
  */
  private disconnectFromDeltaStream(reason: string): boolean {
  this.pendingReconnect = false;
  - this.downgradedConnection = false;
  if (this.connection === undefined) {
  return false;
  @@ -799,7 +790,7 @@ export class ConnectionManager implements IConnectionManager {
  // Note that we also want nacks to be rare and be treated as catastrophic failures.
  // Be careful with reentrancy though - disconnected event should not be be raised in the
  // middle of the current workflow, but rather on clean stack!
  - if (this.connectionMode === "read" || this.downgradedConnection) {
  + if (this.connectionMode === "read") {
  if (!this.pendingReconnect) {
  this.pendingReconnect = true;
  Promise.resolve().then(async () => {
  @@ -842,7 +833,19 @@ export class ConnectionManager implements IConnectionManager {
  if (clientId === this.clientId) {
  // We have been kicked out from quorum
  this.logger.sendPerformanceEvent({ eventName: "ReadConnectionTransition" });
  - this.downgradedConnection = true;
  +
  + // Please see #8483 for more details on why maintaining connection further as is would not work.
  + // Short story - connection properties are immutable, and many processes (consensus DDSs, summarizer)
  + // assume that connection stays "write" connection until disconnect, and act accordingly, which may
  + // not work well with de-facto "read" connection we are in after receiving own leave op on timeout.
  + // Clients need to be able to transition to "read" state after some time of inactivity!
  + // Note - this may close container!
  + this.reconnect(
  + "read", // connectionMode
  + "Switch to read", // message
  + ).catch((error) => {
  + this.logger.sendErrorEvent({ eventName: "SwitchToReadConnection"}, error);
  + });
  }
  }
  }
  