Replace SVG with PNG graphics in documentation #235

Merged
lars.winzer merged 4 commits from chore/50-change-used-markdown-embed-technique into main 2026-04-05 12:48:43 +02:00
3 changed files with 10 additions and 11 deletions
Showing only changes of commit b8a0c224cf - Show all commits
+1 -1
View File
@@ -6,7 +6,7 @@ Each command consists of four classes: a **Parser**, a **Request**, a **Handler*
The infrastructure for routing and dispatching commands lives in the `network/` layer and is intentionally kept generic. The infrastructure for routing and dispatching commands lives in the `network/` layer and is intentionally kept generic.
The concrete implementations for each command live in `app/commands/` and are wired together at startup in `ServerApp`. The concrete implementations for each command live in `app/commands/` and are wired together at startup in `ServerApp`.
![Overview of all components directly related to executing requests](/documents/images/docs/networking/commands/overview.svg) <img src="../../../images/docs/networking/commands/overview.svg" alt="Overview of all components directly related to executing requests" />
## Contents ## Contents
### Guides ### Guides
@@ -10,11 +10,11 @@ An incoming request travels through two sequential pipelines: **parsing** and **
The parsing pipeline converts a stringly-typed `PrimitiveRequest` into a strongly-typed `Request` subclass. The parsing pipeline converts a stringly-typed `PrimitiveRequest` into a strongly-typed `Request` subclass.
The execution pipeline routes that typed request to the correct handler, which produces a `Response`. The execution pipeline routes that typed request to the correct handler, which produces a `Response`.
![Sequence diagram of all involved components to process and respond to an incoming request](/documents/images/docs/networking/commands/sequence_diagram.svg) <img src="../../../images/docs/networking/commands/sequence_diagram.svg" alt="Sequence diagram of all involved components to process and respond to an incoming request" />
## Parsing Pipeline ## Parsing Pipeline
### `CommandParser<T extends Request>` ### `CommandParser<T extends Request>`
![Class diagram of the CommandParser](/documents/images/docs/networking/commands/command_parser.svg) <img src="../../../images/docs/networking/commands/command_parser.svg" alt="Class diagram of the CommandParser" />
The `CommandParser` is a single-method interface responsible for converting a `PrimitiveRequest` into a concrete, typed `Request` subclass. The `CommandParser` is a single-method interface responsible for converting a `PrimitiveRequest` into a concrete, typed `Request` subclass.
Implementations live in `app/commands/<name>/` and are registered by name in `CommandParserDispatcher`. Implementations live in `app/commands/<name>/` and are registered by name in `CommandParserDispatcher`.
@@ -25,7 +25,7 @@ If a required parameter is absent, `RequestParameterAccessor.require(...)` throw
Parsers **do not** perform any domain logic. Their only job is extraction and type conversion. Parsers **do not** perform any domain logic. Their only job is extraction and type conversion.
### `CommandParserDispatcher` ### `CommandParserDispatcher`
![Class diagram of CommandParserDispatcher](/documents/images/docs/networking/commands/command_parser_dispatcher.svg) <img src="../../../images/docs/networking/commands/command_parser_dispatcher.svg" alt="Class diagram of CommandParserDispatcher" />
The `CommandParserDispatcher` holds a map from command name strings (e.g. `"PING"`) to their corresponding `CommandParser`. The `CommandParserDispatcher` holds a map from command name strings (e.g. `"PING"`) to their corresponding `CommandParser`.
When the `SessionReader` receives a `PrimitiveRequest`, it calls `dispatcher.parse(...)`, which looks up the parser by the request's command string and delegates parsing. When the `SessionReader` receives a `PrimitiveRequest`, it calls `dispatcher.parse(...)`, which looks up the parser by the request's command string and delegates parsing.
@@ -33,7 +33,7 @@ When the `SessionReader` receives a `PrimitiveRequest`, it calls `dispatcher.par
If no parser is registered for the command name, `parse(...)` throws an `UnknownCommandException`, which `SessionReader` catches and converts into an `UNKNOWN_COMMAND` error response for the client. If no parser is registered for the command name, `parse(...)` throws an `UnknownCommandException`, which `SessionReader` catches and converts into an `UNKNOWN_COMMAND` error response for the client.
### `RequestParameterAccessor` ### `RequestParameterAccessor`
![Class diagram of RequestParameterAccessor](/documents/images/docs/networking/commands/request_parameter_accessor.svg) <img src="../../../images/docs/networking/commands/request_parameter_accessor.svg" alt="Class diagram of RequestParameterAccessor" />
The `RequestParameterAccessor` is a helper provided to parsers for reading typed parameter values from a `PrimitiveRequest`. The `RequestParameterAccessor` is a helper provided to parsers for reading typed parameter values from a `PrimitiveRequest`.
It indexes the parameter list by key on construction for O(1) lookups. It indexes the parameter list by key on construction for O(1) lookups.
@@ -54,7 +54,7 @@ The `RequestParameterAccessor` wraps it in a `ParameterParseException`.
## Execution Pipeline ## Execution Pipeline
### `Request` ### `Request`
![Class diagram of Request](/documents/images/docs/networking/commands/request.svg) <img src="../../../images/docs/networking/commands/request.svg" alt="Class diagram of the Request" />
The `Request` is the abstract base class for all typed command requests. It carries a `RequestContext`, an immutable record containing the originating `SessionId` and the numeric `requestId`. The `Request` is the abstract base class for all typed command requests. It carries a `RequestContext`, an immutable record containing the originating `SessionId` and the numeric `requestId`.
Both of which are later used by the handler to direct the response to the correct session. Both of which are later used by the handler to direct the response to the correct session.
@@ -62,7 +62,7 @@ Both of which are later used by the handler to direct the response to the correc
Concrete subclasses add command-specific fields, all set via constructor. Requests are immutable value objects. They carry data, not behaviour. Concrete subclasses add command-specific fields, all set via constructor. Requests are immutable value objects. They carry data, not behaviour.
### `CommandHandler<T extends Request>` ### `CommandHandler<T extends Request>`
![Class diagram of CommandHandler](/documents/images/docs/networking/commands/command_handler.svg) <img src="../../../images/docs/networking/commands/command_handler.svg" alt="Class diagram of the CommandHandler" />
The `CommandHandler` is a single-method interface responsible for executing a typed request. The `CommandHandler` is a single-method interface responsible for executing a typed request.
The handler contains the domain logic: reading from registries and managers, modifying state, and dispatching a response via the `ResponseDispatcher`. The handler contains the domain logic: reading from registries and managers, modifying state, and dispatching a response via the `ResponseDispatcher`.
@@ -71,7 +71,7 @@ Handlers receive their dependencies (the `ResponseDispatcher`, registries and ma
This keeps them fully testable without the network layer. This keeps them fully testable without the network layer.
### `CommandRouter` ### `CommandRouter`
![Class diagram of CommandRouter](/documents/images/docs/networking/commands/command_router.svg) <img src="../../../images/docs/networking/commands/command_router.svg" alt="Class diagram of the CommandRouter" />
The `CommandRouter` maps `Request` subclasses to their handlers using the request's runtime class as the key. The `CommandRouter` maps `Request` subclasses to their handlers using the request's runtime class as the key.
The type safety of `register(...)` ensures that a handler can only be registered for the exact type it is parameterised on. The type safety of `register(...)` ensures that a handler can only be registered for the exact type it is parameterised on.
@@ -81,7 +81,7 @@ If no handler is registered for the given request type, `execute(...)` throws `U
Unlike `UnknownCommandException` (which covers unknown command strings), this exception indicates a programming error i.e. a parser was registered without a corresponding handler. Unlike `UnknownCommandException` (which covers unknown command strings), this exception indicates a programming error i.e. a parser was registered without a corresponding handler.
## Response Types ## Response Types
![Class diagram of the response interface and built-in implementations](/documents/images/docs/networking/commands/response_types.svg) <img src="../../../images/docs/networking/commands/response_types.svg" alt="Class diagram of the response interface and built-in implementations" />
The `Response` is the abstract base for all server responses. Its two concrete branches are `SuccessResponse` (prefix `+OK`) and `ErrorResponse` (prefix `-ERR`). The `Response` is the abstract base for all server responses. Its two concrete branches are `SuccessResponse` (prefix `+OK`) and `ErrorResponse` (prefix `-ERR`).
Command-specific responses extend `SuccessResponse` and populate the body using the `ResponseBodyBuilder`. Command-specific responses extend `SuccessResponse` and populate the body using the `ResponseBodyBuilder`.
@@ -26,8 +26,7 @@ Responses start with `+OK` on success or `-ERR` when something goes wrong. Comma
We don't use HTTP, there's no JSON body, no headers. Just a raw socket, a text stream, and a clearly defined set of commands. We don't use HTTP, there's no JSON body, no headers. Just a raw socket, a text stream, and a clearly defined set of commands.
## Core Components & Their Roles ## Core Components & Their Roles
<img src="../../images/docs/networking/server-architecure/networking_components.svg" alt="PlantUML diagram of all components outlined in this document" />
![PlantUML diagramm of all components outlined in this document](/documents/images/docs/networking/server-architecure/networking_components.svg)
Here's a quick rundown of the main building blocks: Here's a quick rundown of the main building blocks: