From 61c4756a8adb14e5ae9088690de073254a11eb55 Mon Sep 17 00:00:00 2001 From: Alex Le Date: Fri, 24 Jul 2026 14:17:55 -0700 Subject: [PATCH 1/3] ci: updated deployment process to ci with draft contents Signed-off-by: Alex Le --- .github/workflows/check-csharp-examples.yml | 2 +- .github/workflows/ci-cd.yml | 2 +- .github/workflows/deploy.yml | 4 +- .github/workflows/static-checks.yml | 2 +- CONTRIBUTING.md | 51 +++++++++++++++++---- src/components/Draft.astro | 10 ++++ 6 files changed, 57 insertions(+), 14 deletions(-) create mode 100644 src/components/Draft.astro diff --git a/.github/workflows/check-csharp-examples.yml b/.github/workflows/check-csharp-examples.yml index d54f37ba..ae6a2641 100644 --- a/.github/workflows/check-csharp-examples.yml +++ b/.github/workflows/check-csharp-examples.yml @@ -2,7 +2,7 @@ name: Check C# Examples on: pull_request: - branches: [main, public] + branches: [main] permissions: contents: read diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index a765f95f..70c1e70d 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -2,7 +2,7 @@ name: CI/CD on: pull_request: - branches: [main, public] + branches: [main] workflow_dispatch: workflow_call: diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index c4129eb6..9b8eafc5 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -4,7 +4,7 @@ on: workflow_dispatch: push: branches: - - public + - main jobs: # Call the CI/CD workflow to build the site @@ -16,7 +16,7 @@ jobs: # Deploy to GitHub Pages deploy: needs: build - if: github.ref == 'refs/heads/public' + if: github.ref == 'refs/heads/main' runs-on: ubuntu-latest permissions: contents: read diff --git a/.github/workflows/static-checks.yml b/.github/workflows/static-checks.yml index b201a068..20083d7b 100644 --- a/.github/workflows/static-checks.yml +++ b/.github/workflows/static-checks.yml @@ -2,7 +2,7 @@ name: Static Checks on: pull_request: - branches: [main, public] + branches: [main] workflow_dispatch: workflow_call: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 86bd1eb4..c3713854 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,18 +2,51 @@ Thank you for your interest in contributing to the Valkey GLIDE documentation! -## Branches Overview +## Deployment Model -| Branch | Purpose | -| -------- | -------------------------------------------------------------------------------- | -| `main` | Integration branch — all PRs target here | -| `public` | Production — deploys the live site at [glide.valkey.io](https://glide.valkey.io) | +`main` is the single source of truth. Every merge to `main` automatically deploys the live site at [glide.valkey.io](https://glide.valkey.io). -In general: +To make a documentation content change, open PRs against `main`. The following is the process for adding and releasing documentation contents +onto the live site. -- Open all PRs against `main`. -- On release day, `main` is merged onto `public` triggering a deployment. -- Only urgent fixes are accepted directly into `public`. +### Unreleased content + +Content not ready for release can be merged asap if they are marked as draft. Draft contents are hidden from the production site. + +**Draft Page** — set `draft: true` in frontmatter. The page is not rendered in production builds but visible in `pnpm dev`. +Always use `draft-reason` to mark when the page can be release. + +``` +--- +title: My New Feature +description: ... +draft: true +draft-reason: For release 2.5 +--- +``` + +**Draft Section** (e.g., one language's example tab) — wrap it in the `` component. Always use `draft-reason` to mark +when the page can be release. + +```mdx +import Draft from "@components/Draft.astro"; + + + ... + + ... + + +``` + +### Draft rules + +1. **Do not add a manual sidebar entry in `astro.config.mjs` for a draft page** — the production build fails with `The slug "..." does not exist`. Autogenerated sidebar sections handle drafts gracefully; otherwise keep the entry commented out until release. +2. **Published pages must not link to draft pages** — `starlight-links-validator` fails the build. + +### Release Process + +Create PR to flip remove the drafts. It is important that `draft-reason` were added to be able to locate sections for release. ## Getting Started diff --git a/src/components/Draft.astro b/src/components/Draft.astro new file mode 100644 index 00000000..5168cda2 --- /dev/null +++ b/src/components/Draft.astro @@ -0,0 +1,10 @@ +--- +/** + * Inline equivalent of Starlight's page-level `draft: true` frontmatter: + * hides its children in production builds; shows them in dev mode. + * + * To release the content, delete the wrapping tags. + */ +--- + +{import.meta.env.DEV && } From 5d4eecd53323c2aa7266e27c981118c135b6874a Mon Sep 17 00:00:00 2001 From: Alex Le Date: Fri, 24 Jul 2026 14:18:07 -0700 Subject: [PATCH 2/3] format: applied formatting Signed-off-by: Alex Le --- CONTRIBUTING.md | 6 +- .../client-features/client-side-caching.mdx | 3 +- .../connections/resilience-best-practices.mdx | 163 +++++++++--------- 3 files changed, 83 insertions(+), 89 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c3713854..996adf0c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -13,7 +13,7 @@ onto the live site. Content not ready for release can be merged asap if they are marked as draft. Draft contents are hidden from the production site. -**Draft Page** — set `draft: true` in frontmatter. The page is not rendered in production builds but visible in `pnpm dev`. +**Draft Page** — set `draft: true` in frontmatter. The page is not rendered in production builds but visible in `pnpm dev`. Always use `draft-reason` to mark when the page can be release. ``` @@ -21,11 +21,11 @@ Always use `draft-reason` to mark when the page can be release. title: My New Feature description: ... draft: true -draft-reason: For release 2.5 +draft-reason: For release 2.5 --- ``` -**Draft Section** (e.g., one language's example tab) — wrap it in the `` component. Always use `draft-reason` to mark +**Draft Section** (e.g., one language's example tab) — wrap it in the `` component. Always use `draft-reason` to mark when the page can be release. ```mdx diff --git a/src/content/docs/concepts/client-features/client-side-caching.mdx b/src/content/docs/concepts/client-features/client-side-caching.mdx index ba8f5d27..7862473e 100644 --- a/src/content/docs/concepts/client-features/client-side-caching.mdx +++ b/src/content/docs/concepts/client-features/client-side-caching.mdx @@ -535,11 +535,10 @@ Multiple clients can share the same cache instance by passing the same `ClientSi ## Server-Assisted Invalidation Server-assisted invalidation can be enabled in the client side configuration by setting server assisted to true. -You do not need to call [`CLIENT TRACKING`](https://valkey.io/commands/client-tracking/) yourself; GLIDE issues `CLIENT TRACKING ON BCAST` on your behalf during connection setup. +You do not need to call [`CLIENT TRACKING`](https://valkey.io/commands/client-tracking/) yourself; GLIDE issues `CLIENT TRACKING ON BCAST` on your behalf during connection setup. Once enabled, the client receives push invalidation messages from the server whenever a cached key is modified, eliminating the staleness window inherent in TTL-only mode — the server notifies the client immediately when data changes, and the client removes the stale entry from its local cache. - ### Enabling server-assisted mode diff --git a/src/content/docs/how-to/connections/resilience-best-practices.mdx b/src/content/docs/how-to/connections/resilience-best-practices.mdx index b744d702..5c3860dc 100644 --- a/src/content/docs/how-to/connections/resilience-best-practices.mdx +++ b/src/content/docs/how-to/connections/resilience-best-practices.mdx @@ -12,80 +12,75 @@ This guide covers configuration and operational practices that help Valkey GLIDE A resilient client combines request timeout, inflight limiting, and the circuit breaker: - - -```python -from glide import ( - GlideClusterClient, - GlideClusterClientConfiguration, - ClientCircuitBreakerConfiguration, - NodeAddress, -) - -config = GlideClusterClientConfiguration( - addresses=[NodeAddress(host="localhost", port=6379)], - request_timeout=500, - inflight_requests_limit=1000, - client_circuit_breaker=ClientCircuitBreakerConfiguration(), -) -client = await GlideClusterClient.create(config) -``` - - - - -```java -import glide.api.GlideClusterClient; -import glide.api.models.configuration.GlideClusterClientConfiguration; -import glide.api.models.configuration.ClientCircuitBreakerConfiguration; -import glide.api.models.configuration.NodeAddress; - -GlideClusterClient client = GlideClusterClient.createClient( - GlideClusterClientConfiguration.builder() - .address(NodeAddress.builder().host("localhost").port(6379).build()) - .requestTimeout(500) - .inflightRequestsLimit(1000) - .clientCircuitBreakerConfiguration( - ClientCircuitBreakerConfiguration.builder().build()) - .build() -).get(); -``` - - - - -```typescript -import { GlideClusterClient } from "@valkey/valkey-glide"; - -const client = await GlideClusterClient.createClient({ - addresses: [{ host: "localhost", port: 6379 }], - requestTimeout: 500, - inflightRequestsLimit: 1000, - clientCircuitBreaker: {}, -}); -``` - - - - -```go -import ( - "time" - - glide "github.com/valkey-io/valkey-glide/go/v2" - "github.com/valkey-io/valkey-glide/go/v2/config" -) - -clientConfig := config.NewClusterClientConfiguration(). - WithAddress(&config.NodeAddress{Host: "localhost", Port: 6379}). - WithRequestTimeout(500 * time.Millisecond). - WithInflightRequestsLimit(1000). - WithClientCircuitBreaker(&config.ClientCircuitBreakerConfiguration{}) - -client, err := glide.NewClusterClient(clientConfig) -``` - - + + ```python + from glide import ( + GlideClusterClient, + GlideClusterClientConfiguration, + ClientCircuitBreakerConfiguration, + NodeAddress, + ) + + config = GlideClusterClientConfiguration( + addresses=[NodeAddress(host="localhost", port=6379)], + request_timeout=500, + inflight_requests_limit=1000, + client_circuit_breaker=ClientCircuitBreakerConfiguration(), + ) + client = await GlideClusterClient.create(config) + ``` + + + + ```java + import glide.api.GlideClusterClient; + import glide.api.models.configuration.GlideClusterClientConfiguration; + import glide.api.models.configuration.ClientCircuitBreakerConfiguration; + import glide.api.models.configuration.NodeAddress; + + GlideClusterClient client = GlideClusterClient.createClient( + GlideClusterClientConfiguration.builder() + .address(NodeAddress.builder().host("localhost").port(6379).build()) + .requestTimeout(500) + .inflightRequestsLimit(1000) + .clientCircuitBreakerConfiguration( + ClientCircuitBreakerConfiguration.builder().build()) + .build() + ).get(); + ``` + + + + ```typescript + import { GlideClusterClient } from "@valkey/valkey-glide"; + + const client = await GlideClusterClient.createClient({ + addresses: [{ host: "localhost", port: 6379 }], + requestTimeout: 500, + inflightRequestsLimit: 1000, + clientCircuitBreaker: {}, + }); + ``` + + + + ```go + import ( + "time" + + glide "github.com/valkey-io/valkey-glide/go/v2" + "github.com/valkey-io/valkey-glide/go/v2/config" + ) + + clientConfig := config.NewClusterClientConfiguration(). + WithAddress(&config.NodeAddress{Host: "localhost", Port: 6379}). + WithRequestTimeout(500 * time.Millisecond). + WithInflightRequestsLimit(1000). + WithClientCircuitBreaker(&config.ClientCircuitBreakerConfiguration{}) + + client, err := glide.NewClusterClient(clientConfig) + ``` + ## Single Client Instance @@ -111,11 +106,11 @@ The `inflightRequestsLimit` controls how many concurrent requests a single clien **Key points:** -- The inflight limit should accommodate your expected concurrency: at throughput `T` ops/s with average latency `L` seconds, you need roughly `T × L` inflight slots (e.g., 50k ops/s at 1ms = ~50 slots, 50k ops/s at 10ms = ~500 slots). -- When the limit is reached, new requests block until a slot frees up. The circuit breaker (if enabled) rejects before this blocking occurs. -- If using Java with `ForkJoinPool.managedBlock()` (common in Akka, Play, or reactive frameworks), set the limit to 2-3x your thread pool size. This prevents thread explosion where `managedBlock()` spawns compensating threads faster than requests complete. -- If you see "inflight requests limit reached" warnings in logs, either increase the limit or reduce concurrency at the application level. -- Setting the limit too high risks memory pressure under sustained backpressure. The default of 1000 is appropriate for most workloads. +* The inflight limit should accommodate your expected concurrency: at throughput `T` ops/s with average latency `L` seconds, you need roughly `T × L` inflight slots (e.g., 50k ops/s at 1ms = ~50 slots, 50k ops/s at 10ms = ~500 slots). +* When the limit is reached, new requests block until a slot frees up. The circuit breaker (if enabled) rejects before this blocking occurs. +* If using Java with `ForkJoinPool.managedBlock()` (common in Akka, Play, or reactive frameworks), set the limit to 2-3x your thread pool size. This prevents thread explosion where `managedBlock()` spawns compensating threads faster than requests complete. +* If you see "inflight requests limit reached" warnings in logs, either increase the limit or reduce concurrency at the application level. +* Setting the limit too high risks memory pressure under sustained backpressure. The default of 1000 is appropriate for most workloads. ## Thread Pool Sizing (Java) @@ -168,11 +163,11 @@ See the dedicated [Circuit Breaker guide](/how-to/connections/circuit-breaker) f **Key points:** -- Enable CB for workloads where thread exhaustion is a concern during outages. -- The CB rejects before the request reaches the network, so rejections are near-zero-cost. -- Enable `countTimeouts` to protect against dead or unreachable nodes. In cluster mode, dead nodes surface primarily as timeouts, so this flag is required for the CB to trip on sustained node outages. -- Recovery is optimistic: in HalfOpen, all traffic is allowed through. After consecutive successes the breaker closes. If a failure occurs, it returns to Open. -- When the CB rejects, handle the `CircuitBreakerException`/`CircuitBreakerError` in your application by returning a cached or degraded response, or signaling the caller to retry after a delay. +* Enable CB for workloads where thread exhaustion is a concern during outages. +* The CB rejects before the request reaches the network, so rejections are near-zero-cost. +* Enable `countTimeouts` to protect against dead or unreachable nodes. In cluster mode, dead nodes surface primarily as timeouts, so this flag is required for the CB to trip on sustained node outages. +* Recovery is optimistic: in HalfOpen, all traffic is allowed through. After consecutive successes the breaker closes. If a failure occurs, it returns to Open. +* When the CB rejects, handle the `CircuitBreakerException`/`CircuitBreakerError` in your application by returning a cached or degraded response, or signaling the caller to retry after a delay. ## Standalone vs Cluster From 172a1a04d169264a892f8cef8a9863c107c342c2 Mon Sep 17 00:00:00 2001 From: Alex Le Date: Thu, 30 Jul 2026 12:48:12 -0700 Subject: [PATCH 3/3] update: new 2 branch release process. Signed-off-by: Alex Le --- .github/workflows/check-csharp-examples.yml | 2 +- .github/workflows/ci-cd.yml | 2 +- .github/workflows/deploy.yml | 4 +- .github/workflows/static-checks.yml | 2 +- CONTRIBUTING.md | 56 ++++++++++++++------- 5 files changed, 43 insertions(+), 23 deletions(-) diff --git a/.github/workflows/check-csharp-examples.yml b/.github/workflows/check-csharp-examples.yml index ae6a2641..d54f37ba 100644 --- a/.github/workflows/check-csharp-examples.yml +++ b/.github/workflows/check-csharp-examples.yml @@ -2,7 +2,7 @@ name: Check C# Examples on: pull_request: - branches: [main] + branches: [main, public] permissions: contents: read diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 70c1e70d..a765f95f 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -2,7 +2,7 @@ name: CI/CD on: pull_request: - branches: [main] + branches: [main, public] workflow_dispatch: workflow_call: diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 9b8eafc5..c4129eb6 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -4,7 +4,7 @@ on: workflow_dispatch: push: branches: - - main + - public jobs: # Call the CI/CD workflow to build the site @@ -16,7 +16,7 @@ jobs: # Deploy to GitHub Pages deploy: needs: build - if: github.ref == 'refs/heads/main' + if: github.ref == 'refs/heads/public' runs-on: ubuntu-latest permissions: contents: read diff --git a/.github/workflows/static-checks.yml b/.github/workflows/static-checks.yml index 20083d7b..b201a068 100644 --- a/.github/workflows/static-checks.yml +++ b/.github/workflows/static-checks.yml @@ -2,7 +2,7 @@ name: Static Checks on: pull_request: - branches: [main] + branches: [main, public] workflow_dispatch: workflow_call: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 996adf0c..419d65f6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,17 +4,45 @@ Thank you for your interest in contributing to the Valkey GLIDE documentation! ## Deployment Model -`main` is the single source of truth. Every merge to `main` automatically deploys the live site at [glide.valkey.io](https://glide.valkey.io). +We use two branches: -To make a documentation content change, open PRs against `main`. The following is the process for adding and releasing documentation contents -onto the live site. +| Branch | Purpose | +| -------- | ----------------------------------------------------------------------------------------------------- | +| `main` | Integration branch. Source of truth. All PRs target here. Content on `main` is awaiting release. | +| `public` | Production branch. deploys the live site at [glide.valkey.io](https://glide.valkey.io) on every push. | -### Unreleased content +All documentation changes flow through `main` first, then are promoted to `public` on release. -Content not ready for release can be merged asap if they are marked as draft. Draft contents are hidden from the production site. +### Contribution Flow -**Draft Page** — set `draft: true` in frontmatter. The page is not rendered in production builds but visible in `pnpm dev`. -Always use `draft-reason` to mark when the page can be release. +1. Open your PR against `main`. +2. Once approved and CI passes, merge to `main`. Merge early and often to avoid big-bang release-day merges. +3. Content sits on `main` until the next release. + +### Release Process + +`main` is the source of truth. On release day, a maintainer resets `public` to `main`'s HEAD and force-pushes: + +```bash +git fetch origin +git push origin +origin/main:public +``` + +Any contents on `main` that isn't ready to go live should be disabled (see [Unreleased Content](#unreleased-content)). + +### Applying a Hotfix + +For urgent fixes to the live site that can't wait for the next release: + +1. Open a PR targeting `public`. +2. Once merged, deployment will start automatically. +3. **Backport the same change to `main` immediately**. Because releases reset `public` to `main` HEAD, any hotfix that isn't on `main` before the next release will be erased. + +### Unreleased Content + +Content that has landed on `main` but isn't ready for release yet must be marked as draft so it doesn't appear on the live site when `public` is next updated. + +**Draft Page** — set `draft: true` in frontmatter. The page is excluded from production builds but visible in `pnpm dev`. Always include a `draft-reason` so releases can locate what to unflip. ``` --- @@ -25,8 +53,9 @@ draft-reason: For release 2.5 --- ``` -**Draft Section** (e.g., one language's example tab) — wrap it in the `` component. Always use `draft-reason` to mark -when the page can be release. +Remove the page from sidebar entry in `astro.config.mjs` as it will fail the build if linked explicitly. + +**Draft Section** (e.g., one language's example tab) — wrap the section in the `` component. Always include a `draft-reason`. ```mdx import Draft from "@components/Draft.astro"; @@ -39,15 +68,6 @@ import Draft from "@components/Draft.astro"; ``` -### Draft rules - -1. **Do not add a manual sidebar entry in `astro.config.mjs` for a draft page** — the production build fails with `The slug "..." does not exist`. Autogenerated sidebar sections handle drafts gracefully; otherwise keep the entry commented out until release. -2. **Published pages must not link to draft pages** — `starlight-links-validator` fails the build. - -### Release Process - -Create PR to flip remove the drafts. It is important that `draft-reason` were added to be able to locate sections for release. - ## Getting Started 1. Fork the repository