Skip to content

Commit 4512adb

Browse files
committed
Update docs
1 parent f28bb88 commit 4512adb

5 files changed

Lines changed: 48 additions & 41 deletions

File tree

docs/guide/caching.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,13 @@ request.Headers.CacheControl = new CacheControlHeaderValue
151151

152152
## Sharing a Cache Store
153153

154-
By default each named client gets its own `CacheStore`. To share a single store across multiple named clients — for example, to deduplicate in-flight requests across services — create a `CacheStore` once and pass it directly:
154+
By default each named client gets its own cache. To share a single store across multiple named clients — for example, to serve the same cached responses to parallel services — implement `ICacheStore` and pass the same instance to each client:
155155

156156
```csharp
157-
var sharedStore = new CacheStore();
157+
using TurboHTTP.Protocol.Caching;
158+
159+
// Your thread-safe ICacheStore implementation
160+
ICacheStore sharedStore = new MySharedCacheStore();
158161

159162
builder.Services.AddTurboHttpClient("client-a", options =>
160163
{
@@ -169,6 +172,8 @@ builder.Services.AddTurboHttpClient("client-b", options =>
169172
.WithCache(sharedStore);
170173
```
171174

172-
`CacheStore` is thread-safe and designed for concurrent access from multiple clients.
175+
::: warning Thread safety
176+
When an `ICacheStore` is shared across multiple clients it will receive concurrent reads and writes. Your implementation must be thread-safe.
177+
:::
173178

174179
See the [Configuration guide](./configuration) for more details on cache setup.

docs/guide/cookies.md

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -107,39 +107,31 @@ A cookie with no `Max-Age` and no `Expires` is a **session cookie** — it lives
107107
Set-Cookie: sid=abc123 ← no expiry: lasts until the client is disposed
108108
```
109109

110-
## Working with `CookieJar` Directly
110+
## Sharing a Cookie Store
111111

112-
`CookieJar` is a public class. You can construct one independently to pre-populate cookies, test cookie matching logic, or share a jar across request processing outside the pipeline.
112+
By default each named client gets its own isolated cookie store. To share cookies across multiple clients — for example, so that a login performed by one client is visible to another — implement `ICookieStore` and pass the same instance to each:
113113

114114
```csharp
115115
using TurboHTTP.Protocol.Cookies;
116116

117-
var jar = new CookieJar();
117+
// Your thread-safe ICookieStore implementation
118+
ICookieStore sharedStore = new MySharedCookieStore();
118119

119-
// Simulate a server response that sets a cookie
120-
var response = new HttpResponseMessage();
121-
response.Headers.TryAddWithoutValidation("Set-Cookie", "session=abc123; Path=/; Secure");
122-
jar.ProcessResponse(new Uri("https://api.example.com"), response);
120+
builder.Services.AddTurboHttpClient("auth", options =>
121+
{
122+
options.BaseAddress = new Uri("https://auth.example.com");
123+
})
124+
.WithCookies(sharedStore);
123125

124-
Console.WriteLine($"Cookies stored: {jar.Count}"); // → 1
125-
126-
// Inspect what would be injected into a request
127-
var request = new HttpRequestMessage(HttpMethod.Get, "https://api.example.com/data");
128-
jar.AddCookiesToRequest(new Uri("https://api.example.com/data"), ref request);
129-
// request.Headers["Cookie"] now contains "session=abc123"
130-
131-
// Clear all stored cookies (e.g., on logout)
132-
jar.Clear();
133-
Console.WriteLine($"Cookies after clear: {jar.Count}"); // → 0
126+
builder.Services.AddTurboHttpClient("api", options =>
127+
{
128+
options.BaseAddress = new Uri("https://api.example.com");
129+
})
130+
.WithCookies(sharedStore);
134131
```
135132

136-
### Clearing cookies on logout
137-
138-
Call `Clear()` on the jar when a user logs out to remove all stored cookies:
139-
140-
```csharp
141-
// After a successful logout response:
142-
jar.Clear();
143-
```
133+
A cookie set during login on the `auth` client will now be available to the `api` client.
144134

145-
Since the per-client `CookieJar` is managed internally by the pipeline, clearing it in tests or custom integrations requires direct access to the jar instance used at construction time.
135+
::: warning Thread safety
136+
When an `ICookieStore` is shared across multiple clients it will receive concurrent reads and writes. Your implementation must be thread-safe.
137+
:::

notes/Architecture/Layers/16-PROTOCOL_LAYER.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,10 +236,18 @@ src/TurboHTTP/Protocol/
236236
│ ├── ContentEncodingDecoder.cs
237237
│ └── …
238238
├── Caching/ # HTTP Caching (RFC 9111)
239-
│ ├── CacheStore.cs
239+
│ ├── ICacheStore.cs # Store interface (custom backend extension point)
240+
│ ├── MemoryCacheStore.cs # Default in-memory store (actor-confined)
241+
│ ├── CacheStoreEntry.cs # Stored response snapshot (Vary, ETag, freshness)
242+
│ ├── CacheControlStoreEntry.cs
240243
│ ├── CacheFreshnessEvaluator.cs
244+
│ ├── CacheValidationRequestBuilder.cs
245+
│ ├── CacheControlParser.cs
241246
│ └── …
242247
└── Cookies/ # Cookie management (RFC 6265)
248+
├── ICookieStore.cs # Store interface (custom backend extension point)
249+
├── MemoryCookieStore.cs # Default in-memory store (actor-confined)
250+
├── CookieStoreEntry.cs # Persisted cookie record
243251
├── CookieJar.cs
244252
└── CookieParser.cs
245253
```

notes/Architecture/Status/04-CURRENT_STATE_SUMMARY.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,8 @@ ConnectionLease
216216

217217
### Thread Safety
218218
-`ConnectionPool` is thread-safe (SemaphoreSlim, ConcurrentQueue)
219-
-`CookieJar` is thread-safe (locking on writes)
220-
-`HttpCacheStore` is thread-safe (ReaderWriterLockSlim)
219+
-`CookieJar` is actor-confined — `MemoryCookieStore` uses a plain `List<T>` (no locking needed)
220+
-`MemoryCacheStore` is actor-confined — uses a plain `Dictionary` (no locking needed)
221221
- ✅ Akka stages are single-threaded per actor
222222

223223
### Testing

notes/RFC/RFC9111/RFC9111.md

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ source_url: "https://www.rfc-editor.org/rfc/rfc9111"
1616
|--------|-------|
1717
| **Compliance Score** | 78/100 |
1818
| **Implementation Status** | ✅ Complete |
19-
| **Implementation Path** | `TurboHTTP/Protocol/RFC9111/` |
20-
| **Unit Test Files** | `TurboHTTP.Tests/RFC9111/`4 files, 75 tests |
21-
| **Stream Test Files** | `TurboHTTP.StreamTests/RFC9111/` |
19+
| **Implementation Path** | `TurboHTTP/Protocol/Caching/` |
20+
| **Unit Test Files** | `TurboHTTP.Tests/Caching/`6 files |
21+
| **Stream Test Files** | `TurboHTTP.StreamTests/Caching/` — 3 files |
2222
| **Key Gaps** | Shared cache support, pragma: no-cache, heuristic freshness, cache key normalization |
2323

2424
## Core Concepts
@@ -36,10 +36,12 @@ source_url: "https://www.rfc-editor.org/rfc/rfc9111"
3636

3737
| Component | File | Purpose |
3838
|-----------|------|---------|
39-
| `HttpCacheStore` | `Protocol/RFC9111/HttpCacheStore.cs` | Thread-safe in-memory LRU cache with Vary support |
40-
| `CacheFreshnessEvaluator` | `Protocol/RFC9111/CacheFreshnessEvaluator.cs` | §4.2 freshness lifetime, current age, heuristic |
41-
| `CacheValidationRequestBuilder` | `Protocol/RFC9111/CacheValidationRequestBuilder.cs` | §4.3 conditional requests, 304 merge |
42-
| `CacheControlParser` | `Protocol/RFC9111/CacheControlParser.cs` | §5.2 Cache-Control directive parsing |
39+
| `ICacheStore` | `Protocol/Caching/ICacheStore.cs` | Store interface — implement for a custom cache backend |
40+
| `MemoryCacheStore` | `Protocol/Caching/MemoryCacheStore.cs` | Default in-memory store (actor-confined, no locking needed) |
41+
| `CacheStoreEntry` | `Protocol/Caching/CacheStoreEntry.cs` | Stored response snapshot with Vary, ETag, freshness metadata |
42+
| `CacheFreshnessEvaluator` | `Protocol/Caching/CacheFreshnessEvaluator.cs` | §4.2 freshness lifetime, current age, heuristic |
43+
| `CacheValidationRequestBuilder` | `Protocol/Caching/CacheValidationRequestBuilder.cs` | §4.3 conditional requests, 304 merge |
44+
| `CacheControlParser` | `Protocol/Caching/CacheControlParser.cs` | §5.2 Cache-Control directive parsing |
4345

4446
### Stages
4547

@@ -51,8 +53,8 @@ source_url: "https://www.rfc-editor.org/rfc/rfc9111"
5153

5254
| Test File | Coverage |
5355
|-----------|----------|
54-
| `TurboHTTP.Tests/RFC9111/` | 75 unit tests — freshness, validation, storage, directives |
55-
| `TurboHTTP.StreamTests/RFC9111/` | Stage behaviour tests — cache lookup and storage stages |
56+
| `TurboHTTP.Tests/Caching/` | Unit tests — freshness, validation, storage, directives, qualified directives |
57+
| `TurboHTTP.StreamTests/Caching/` | Stage behaviour tests — cache lookup, storage, and shared response |
5658

5759
## Sections
5860

0 commit comments

Comments
 (0)