Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 0 additions & 40 deletions .github/workflows/claude.yml

This file was deleted.

74 changes: 0 additions & 74 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ concurrency:
env:
IMAGE: databases-dev
CACHE_KEY: databases-dev-${{ github.event.pull_request.head.sha || github.sha }}
CACHE_5_KEY: databases-dev-cache-5-${{ github.event.pull_request.head.sha || github.sha }}

on: [pull_request, workflow_dispatch]

Expand Down Expand Up @@ -123,76 +122,3 @@ jobs:

- name: Run Tests
run: docker compose exec -T -e XDEBUG_MODE=off tests vendor/bin/paratest --configuration phpunit.xml --functional --processes 4 /usr/src/code/tests/e2e/Adapter/${{matrix.adapter}}Test.php

setup_cache_5:
name: Setup & Build Docker Image (utopia-php/cache 5.x)
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0

- name: Build Docker Image
uses: docker/build-push-action@1104d471370f9806843c095c1db02b5a90c5f8b6 # v3.3.1
with:
context: .
file: Dockerfile
build-args: |
UTOPIA_CACHE_VERSION=^5.1
push: false
tags: ${{ env.IMAGE }}
load: true
cache-from: |
type=gha
type=gha,scope=cache-5
cache-to: type=gha,mode=max,scope=cache-5
outputs: type=docker,dest=/tmp/${{ env.IMAGE }}.tar

- name: Cache Docker Image
uses: actions/cache@6f8efc29b200d32929f49075959781ed54ec270c # v3.5.0
with:
key: ${{ env.CACHE_5_KEY }}
path: /tmp/${{ env.IMAGE }}.tar

cache_5_test:
name: "Cache 5.x Tests (${{ matrix.suite }})"
runs-on: ubuntu-latest
needs: setup_cache_5
strategy:
fail-fast: false
matrix:
include:
- suite: Unit
profiles: ""
path: /usr/src/code/tests/unit
- suite: MariaDB
profiles: "--profile mariadb"
path: /usr/src/code/tests/e2e/Adapter/MariaDBTest.php

steps:
- name: checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Load Cache
uses: actions/cache@6f8efc29b200d32929f49075959781ed54ec270c # v3.5.0
with:
key: ${{ env.CACHE_5_KEY }}
path: /tmp/${{ env.IMAGE }}.tar
fail-on-cache-miss: true

- name: Load and Start Services
run: |
docker load --input /tmp/${{ env.IMAGE }}.tar
docker compose ${{ matrix.profiles }} up -d --wait

- name: Show utopia-php/cache Version
run: |
docker compose exec -T tests php -r '
require "vendor/autoload.php";
echo "utopia-php/cache ", \Composer\InstalledVersions::getPrettyVersion("utopia-php/cache"), PHP_EOL;
'

- name: Run Tests
run: docker compose exec -T -e XDEBUG_MODE=off tests vendor/bin/paratest --configuration phpunit.xml --functional --processes 4 ${{ matrix.path }}
14 changes: 0 additions & 14 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,6 @@ RUN composer install \
--no-scripts \
--prefer-dist

ARG UTOPIA_CACHE_VERSION=""

RUN if [ -n "$UTOPIA_CACHE_VERSION" ]; then \
composer update utopia-php/cache \
--with "utopia-php/cache:$UTOPIA_CACHE_VERSION" \
--with-dependencies \
--ignore-platform-reqs \
--optimize-autoloader \
--no-interaction \
--no-plugins \
--no-scripts \
--prefer-dist; \
fi

FROM php:8.5.8-cli-alpine AS compile

ENV PHP_REDIS_VERSION="6.3.0" \
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"ext-redis": "*",
"utopia-php/validators": "^1.0 || ^2.0",
"utopia-php/console": "^0.1 || ^0.2",
"utopia-php/cache": "^5.2",
"utopia-php/cache": "^6.0",
"utopia-php/pools": "^2.0",
"utopia-php/mongo": "^1.5.4",
"utopia-php/query": "^0.7.2",
Expand Down
14 changes: 7 additions & 7 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions docs/cache-invalidation-state.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Eviction-safe invalidation (breaking change)

The collection's CAS version is its epoch. Its single evictable record contains only writer registrations. Atomic snapshots and CAS replace the started/finished counters, owner sidecars and separately maintained epoch. Eviction creates a fresh identity. Every completion changes the version, including a writer whose registration disappeared, retiring pre-commit fills while preserving newer live writers.

The same opaque versions fence document, definition and query fills. CAS returns the exact identity it committed, or false for a version conflict. Errors and open circuit breakers throw; they are never treated as eviction. Expiry checks use the caller's writer timeout; a reader with a shorter timeout does not delete another caller's live registration. Later writer completion still retires fills made after its timeout.

This requires cache 6.x; the old generation API and compatibility protocol are removed. Redis, Redis multiplexing and Memory support versioning. Database document/query/withCache caching is bypassed on unsupported adapters; ordinary database operations continue. The old cache-5 compatibility CI tier is removed because it is no longer a supported dependency.

No additional Dragonfly or coordination DSN is needed. Drain and stop legacy API/worker/task/migration writers, clear disposable cache data, deploy matching library versions everywhere and resume. Do not mix protocols. Rollback requires the same drain/clear procedure.

A successful post-commit invalidation remains necessary. Durable replay of completions lost during a cache outage is separate work. A cache timeout/OOM must never be interpreted as an empty writer record.
34 changes: 0 additions & 34 deletions src/Database/Cache/Fields.php

This file was deleted.

82 changes: 82 additions & 0 deletions src/Database/Cache/Mutation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php

namespace Utopia\Database\Cache;

use Utopia\Cache\Cache;
use Utopia\Cache\Exception\Unavailable;

/**
* One evictable record holds every writer; its CAS version is the epoch. A cold record
* gets a fresh identity; even a writer whose registration was evicted rotates
* that identity after commit, retiring anything filled while it was in flight.
*/
final readonly class Mutation
{
public function __construct(private Cache $cache)
{
}

public function read(string $key, int $timeout): Epoch
{
return $this->change($key, $timeout);
}

public function begin(string $key, string $token, int $timeout): void
{
$this->change($key, $timeout, $token, true);
}

public function finish(string $key, string $token, int $timeout): void
{
$this->change($key, $timeout, $token);
}

private function change(string $key, int $timeout, ?string $token = null, bool $begin = false): Epoch
{
$key .= '#state';
for ($attempt = 0; $attempt < 16; $attempt++) {
$snapshot = $this->cache->loadVersioned($key);
$state = $snapshot['value'];
$changed = $state === false;
if ($state === false) {
$state = ['owners' => []];
}
if (! \is_array($state) || ! \is_array($state['owners'] ?? null)) {
throw new Unavailable("Invalid cache mutation record '{$key}'");
}
$epoch = $snapshot['version'];
$owners = [];
$now = \time();
foreach ($state['owners'] as $owner => $created) {
if (! \is_string($owner) || ! \is_int($created)) {
throw new Unavailable("Invalid cache writer in '{$key}'");
}
if ($begin || $created + $timeout > $now) {
$owners[$owner] = $created;
} elseif ($token !== null) {
$changed = true;
}
}
if ($token !== null) {
if ($begin) {
$owners[$token] = $now;
} else {
unset($owners[$token]);
}
$changed = true;
}
if ($changed) {
$epoch = $this->cache->compareAndSwap($key, ['owners' => $owners], $snapshot['version']);
if ($epoch === false) {
continue;
}
}

return $owners === []
? new Epoch('active:'.$epoch)
: new Epoch(blockedAt: \min($owners));
}

throw new Unavailable("Cache mutation record kept changing '{$key}'");
}
}
67 changes: 0 additions & 67 deletions src/Database/Cache/Owners.php

This file was deleted.

Loading
Loading