Contents
Maintaining the docs and examples
Documentation and executable examples target the 2.0 SQL mget API.
Checks before merging
Pull-request CI follows the changed files. Extension changes run source tests, sanitizers,
Docker integration and PostgreSQL 14–18 tests on amd64 and arm64. Documentation changes run the
Pages checks; executable-example changes also run PostgreSQL 14–18 smoke tests.
Package inputs retain their separate archive validation. Manual workflow
dispatch remains available. The examples matrix is not repeated on a push to
master; direct pushes that bypass PR checks need a manual examples run.
The examples execute shell blocks from QUICKSTART.md and SQL/configuration
from INSTALL_EXISTING.md on fresh databases, including a non-default port.
The default workload benchmark, common SQL/RESP launcher smoke and Node unit
tests run once, on PostgreSQL 16;
other versions run the functional examples. Throughput is never a pass/fail
threshold. Benchmark records and browser screenshots/traces are retained for
14 days as demo-benchmark-pg16 and browser artifacts.
Quick local checks:
make verify-static source-test source-sanitize
pg_buildext -o shared_preload_libraries=pg_local_cache \
-o pg_local_cache.port=0 \
-o pg_local_cache.database=contrib_regression \
-o pg_local_cache.role=regress_pglc_worker installcheck
docker run --rm -v "$PWD:/repo" -w /repo ubuntu:24.04 test/ci.sh 16
npm --prefix examples/node-postgres ci --ignore-scripts
node --test examples/node-postgres/queries.test.mjs
RESP fuzzing and stress testing
The source test and sanitizer targets replay every file in
fuzz/corpus/resp_parse, checking all strict prefixes of complete seed
commands. Run the replay directly with:
make -C tests/unit check sanitize
With Clang and libFuzzer installed, build and run the parser fuzzer locally:
clang -DPGLC_RESP_STANDALONE -Isrc -g -O1 -fsanitize=fuzzer,address,undefined fuzz/resp_parse_fuzzer.c src/resp.c -o /tmp/resp_parse_fuzzer && /tmp/resp_parse_fuzzer -max_total_time=60 fuzz/corpus/resp_parse
Pull requests run ClusterFuzzLite with AddressSanitizer and
UndefinedBehaviorSanitizer. No infra/helper.py setup is needed for that CI
path.
Against a running PostgreSQL instance with pg_local_cache loaded, the
integration test creates and attaches public.stress_items, runs concurrent
committed and rolled-back writes, RESP readers, invalidations, a cache kill
switch cycle, and malformed input. It checks sampled reads and finishes with
an exact SQL-to-RESP scan after writers stop. Configure PostgreSQL and RESP
connections with the same PG* and PG_LOCAL_CACHE_* environment variables
used by the other integration suites. Run the default 30-second test with:
python3 tests/stress_integration.py
Set PGLC_STRESS_SECONDS=10 for a shorter run. PGLC_STRESS_KEYS,
PGLC_STRESS_WRITERS, and PGLC_STRESS_READERS tune the workload; key count
must exceed configured cache capacity to verify eviction churn.
Releasing the extension
Run scripts/bump-version.sh X.Y.Z to move the non-empty [Unreleased] notes in
CHANGELOG.md into a version section dated in UTC. Review and commit the
changes, then create and push the matching tag:
git tag vX.Y.Z
git push origin vX.Y.Z
Run the documented database examples locally (Docker and Node.js 20+):
docker compose -f examples/compose.yaml up --build --wait
python3 tests/quickstart_docs_smoke.py
docker compose -f examples/compose.yaml down
For PostgreSQL 14, 15, 17 or 18, export PGLC_DEMO_PG before starting Compose.
Use --skip-benchmark on the quickstart check when only testing functionality.
Always run compose down after a failed check too; the demo data is disposable.
After building the site with GitHub Pages' Jekyll builder, check the output:
python3 scripts/check_site.py _site
python3 -m venv /tmp/pglc-browser-tests
/tmp/pglc-browser-tests/bin/pip install -r tests/browser/requirements.txt
/tmp/pglc-browser-tests/bin/python -m playwright install --with-deps chromium webkit
/tmp/pglc-browser-tests/bin/python tests/browser/site_smoke.py _site
The browser suite covers all pages with Chromium and WebKit at 1440, 390 and 320 pixels, plus a mobile case without JavaScript. It checks metadata, HTTP and console errors, overflow, navigation, table of contents, FAQ and clipboard.
Publishing
Pages builds once, validates that output, then publishes the same artifact
on upstream master. Pull requests never deploy. The workflow checks the
published homepage’s HTTP response; it does not repeat the browser suite.
Forks can validate pull requests but do not publish a preview automatically.
Enable Settings → Pages → Source: GitHub Actions before deploying. If deployment fails after validation, rerun the failed job while its Pages artifact exists. After its 14-day retention period, rerun the workflow.
Publishing a result
Keep the extension revision separate from the benchmark harness revision. Record the environment, exact commands, all repetitions, cache counters, and client-side processing. Do not average p99 values or reuse measurements from a different API. Publish the raw results alongside any table on the site.
Search indexing
The project site is https://profundium.github.io/pg_local_cache/. Its sitemap
is generated from the public pages; adding a document does not require a
second URL list. Set last_modified_at only after a substantive content edit.
Do not replace it with the build date.
Search Console and Bing verification tokens go in google_site_verification
and bing_site_verification in site/_config.yml. Empty values emit no tags.
Sitemap: https://profundium.github.io/pg_local_cache/sitemap.xml.
Crawlers use the host-level https://profundium.github.io/robots.txt, managed
in the organization site repository.
The public site uses Google Analytics (G-MHQBYKWZ7W); browser tests stub its
loader so local/CI visits are not recorded. The extension has no telemetry.
Languages and blog articles
English URLs stay at the root. Russian, Spanish, German, French and Simplified
Chinese live under site/ru/, site/es/, site/de/, site/fr/ and site/zh/.
English docs live in root docs/ and are copied into site/docs/ at build time.
site/_data/locales.yml is the language registry; site/_data/en.yml and its
five counterparts contain shared UI and diagram text. Pages work as static HTML,
including language switching.
Every public page has a unique translation_key, a lang and a self-canonical
permalink. Give every translation the same key and heading {#id} anchors.
Translate full prose, titles, descriptions and accessibility labels. Keep
executable examples, API names, measured numbers and raw output unchanged.
Relative links between guides stay within the locale; shared site assets live in
site/assets/, while English documentation and benchmark data live in root
docs/. Check those paths when adding translations.
Write articles in site/blog/ with layout: post, topic (performance,
correctness or application), a publication date and last_modified_at.
Add the complete article under each translated site/<lang>/blog/ directory in
the same change. Use layout: blog for site/blog/index.md and translated
indexes. The shared lists, related articles, sitemap,
language alternates and six Atom feeds are generated from page metadata.
Dates describe publication and substantive edits, never the build time.
Use distinct reader questions for new articles. Link explanations to runnable guides and the API reference; keep performance claims tied to their workload and raw measurements. Follow Google’s localized-page guidance: reciprocal language alternates, a self-canonical for each translation and explicit language links. These checks establish a crawlable artifact, not search-engine indexing or ranking.
Run python3 tests/pages_contract_test.py, then the built-site and browser
checks above. They verify translation coverage, stable anchors and code,
reciprocal hreflang, locale feeds, schema, links and mobile navigation.
Keep Markdown link labels on one source line. The GitHub Pages jekyll-relative-links plugin does not rewrite links whose label contains a newline; the built-site check rejects the resulting .md URLs.