Files
Flash5/CLAUDE.md
T
2026-03-15 01:54:35 +01:00

79 lines
3.8 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Build & Run Commands
```bash
# Build the project
mvn compile
# Package (JAR)
mvn package
# Run (entry point is dev.relism.Main)
mvn exec:java -Dexec.mainClass="dev.relism.Main"
# Clean build artifacts
mvn clean
# Full clean build
mvn clean package
```
No tests exist yet. The project resolves the `fpr-core` dependency from a private Reposilite repository at `https://maven.relism.dev/releases`.
## Architecture Overview
**Flash** is a hand-rolled, zero-allocation HTTP/1.1 server built on raw Java sockets with virtual threads (Java 21). The central design goal is extreme low latency — no intermediate String allocations on the hot path.
### Request Lifecycle
```
Socket → RequestParser → GlobalRouter → AbstractRouter impl → RequestHandler → Response bytes → Socket
```
1. **`RequestParser`** — Reads raw bytes from the socket into an 8 KB buffer and scans for method, path, headers, and body without creating intermediate String objects. All parsed values are wrapped in `ByteView` implementations (see `FastPathViews`).
2. **`GlobalRouter`** — The top-level dispatcher. Holds a sorted list of mounted sub-routers (longest namespace prefix first) and a default internal router. Dispatches each request via byte-level prefix matching (`ByteUtils.startsWith`).
3. **`FastPathRouterImpl`** — The primary router implementation, backed by the external `fpr-core` library. Builds a compiled state machine (`RouterBuilder → FastPathRouter`) for ultra-fast byte-level method+path matching. Routes are marked dirty (`router = null`) when added and lazily recompiled on first request. Thread-local `MatchResult` objects avoid per-request allocation.
4. **`RadixPathRouterImpl`** — Stub; not yet implemented.
### Key Abstractions
- **`AbstractRouter`** — Base class for all routers. Has a `namespace` (byte array for zero-alloc prefix checks) and two abstract methods: `route(Request)` and `addRoute(HttpMethod, String, RequestHandler)`.
- **`RequestHandler`** — Abstract class handlers extend. The `handle(Request, Response)` method returns either a `Response` object or any other value (serialized as the body) or `null`.
- **`SimpleHandler`** — Wraps a `FunctionalHandler` lambda for the fluent DSL (`server.get(path, handler)`).
- **`@Route` annotation** — Applied to `RequestHandler` subclasses to declare their HTTP method and path. Used by `AbstractRouter.register()`.
- **`ByteView`** (`fpr-core` interface) — Zero-copy abstraction over byte sequences. Implemented by `RequestByteView` (slice into the raw buffer), `MethodPathByteView` (virtual concatenation of method + path), `SocketByteView`, and `StringByteView` — all in `FastPathViews`.
### Routing Registration (Two Styles)
**Annotation-based (class handlers):**
```java
@Route(method = "GET", path = "/profile")
public static class ProfileHandler extends RequestHandler { ... }
apiRouter.register(new ProfileHandler()); // namespace "/api" + path "/profile" = "/api/profile"
```
**Fluent DSL (lambdas):**
```java
server.get("/hello", (req, res) -> "Hello World");
```
Paths registered via `addRoute` are prefixed with the router's namespace inside `FastPathRouterImpl.addRoute`.
### Response Writing
`HttpServer` writes HTTP/1.1 responses with pre-calculated static byte arrays (`HTTP_1_1`, `CRLF`, `CONTENT_TYPE`, `CONTENT_LENGTH`) to avoid per-response allocations. `IoUtils.writeInt` writes integer values without String conversion.
### Performance Invariants to Maintain
- No `String` creation on the routing hot path (use `ByteView` and byte arrays).
- Thread-local `MatchResult` reuse in `FastPathRouterContext` — do not allocate per request.
- `GlobalRouter.route` must stay allocation-free (sorted list iterated directly).
- `RequestParser` assumes headers fit in one 8 KB burst read.