# PR#93: The Running Relay Sends the Reaction of matrix react Version: minor > **WARNING:** This document describes only the change applied in this PR. > It may already be outdated once the next PR is merged. > Historic PR documentation is not maintained along with new PRs; treat it as a snapshot. ## Related Links - [werkregie PR#91](https://git.javagil.de/mi/werkregie/pulls/91), `matrix react`, which takes `sync.lock` itself. - [werkregie PR#92](https://git.javagil.de/mi/werkregie/pulls/92), the refactoring of `MatrixSource` that this PR needs. ## Problem `matrix react` takes `sync.lock`, which the running relay holds as long as it runs. An agent stops the relay for each batch of reactions, for about 50 s per call; meanwhile the dashboard misses the relay's report and says that the connection to the machine is lost. ## Non-Goals - No other command through the socket, e.g. a message; only a reaction. - No socket in the network: a Unix domain socket of the user only. - No change of what `matrix react` does in the room. ## Specification ### Feature: the process that holds `sync.lock` sends the reaction of `matrix react` #### Scenario#93.01: the running relay sends the reaction … so that the relay keeps running and the dashboard keeps its report. - **Given** the relay of the machine holds `sync.lock` and serves `control.sock` - **When** an agent runs `werkregie-dashboard matrix react --room "HSAdmin NG" --contains /pulls/329 ✅️` - **Then** the relay sends the reaction with its own client, and the command prints the relay's outcome, e.g. `REACTED` ##### Verified by - [MatrixControlTest "the process that serves the socket sends the reaction and answers with its outcome"](../../dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixControlTest.kt) - [MatrixReactorTest "while another process syncs, the command asks it to send the reaction"](../../dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReactorTest.kt) - [MatrixReactionsTest "a printed line gives back its outcome; another line ends the command"](../../dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReactionsTest.kt) #### Scenario#93.02: without a running relay the command uses a client of its own … so that a reaction works also on a machine without a relay. - **Given** no process holds `sync.lock`, and a `control.sock` of an ended process may be left - **When** the agent runs the command - **Then** nobody answers on the socket, and the command takes `sync.lock` and reacts with a client of its own, as before ##### Verified by - [MatrixControlTest "without a server nobody answers, also on a socket file that an ended process left"](../../dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixControlTest.kt) - [MatrixControlTest "a server replaces the socket file of an ended process"](../../dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixControlTest.kt) #### Scenario#93.03: a holder of the lock that does not answer … so that two clients never use the device's store and keys at once. - **Given** a process holds `sync.lock` but does not serve `control.sock`, e.g. a relay of an older version - **When** the agent runs the command - **Then** nothing is sent, and the command says to restart the relay and ends with exit code 3 ##### Verified by - [MatrixReactorTest "a process that holds the lock but does not answer gets no second client, and the command says how to restart it"](../../dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixReactorTest.kt) #### Scenario#93.04: a failure in the relay … so that the agent sees why no reaction was sent. - **Given** the relay serves `control.sock`, and the room "HSAdmin NG" is not among its rooms - **When** the agent runs the command - **Then** the command prints the relay's message on stderr and ends with exit code 3 ##### Verified by - [MatrixControlTest "a failure of the serving process ends the command with its message"](../../dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixControlTest.kt) - [MatrixControlTest "an answer carries the outcome's line or the failure's message"](../../dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixControlTest.kt) #### Scenario#93.05: the socket takes only a reaction … so that the socket opens no other way into the user's Matrix account. - **Given** the relay serves `control.sock` - **When** a process of the user sends another command, or a reaction without room, text or key - **Then** the relay sends nothing and answers with an error ##### Verified by - [MatrixControlTest "the socket takes only a reaction, with room, text and key"](../../dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixControlTest.kt) - [MatrixControlTest "only the user may use the socket, and it is gone when the server ends"](../../dashboard/src/test/kotlin/de/hoennig/werkregie/dashboard/sources/MatrixControlTest.kt) ## Solution - `MatrixControl`, new: the Unix domain socket `/matrix/control.sock`, one request per connection, one line of JSON each way: `{"command":"react","room":…,"contains":…,"key":…}`, answered by `{"line":"REACTED …"}` or `{"error":"…"}`. `serve` replaces a socket file that an ended process left, sets it to 0600, and answers one request after the other; `ask` returns null when nobody serves, so that the command falls back to a client of its own. - `MatrixSource.sync` serves the socket with its client while it syncs: the relay as well as the local mode. - `MatrixReactor.react(dir, …)` asks the socket first and takes `sync.lock` only when nobody answers; `react(client, …)` waits for the first sync and reacts with any client, the relay's or its own. - A holder of the lock that does not answer, e.g. a relay of an older version or one in its first seconds, makes the command fail with the hint to restart it; the command never opens a second client. - `MatrixReactions.outcome` reads the relay's line back into the outcome, so that exit code and output stay as before. - The socket needs no secret: the directory of the device's keys is 0700, the socket 0600, so only processes of the user reach it, which could run `matrix react` themselves. - `pitestPartial mutationCrapCheck` against main: the highest Mutation-CRAP is 13, `MatrixReactor.entry`; of `MatrixControl` 5, `request`. ## Release Notes - `matrix react` sends its reaction through the running relay or local mode; neither stops for it any more. ## Open Questions None. ## Prerequisite PRs - [werkregie PR#92](https://git.javagil.de/mi/werkregie/pulls/92): each method of `MatrixSource` at a Mutation-CRAP of at most 15; this branch builds on it.