v0.150.0
 1from __future__ import annotations
 2
 3from typing import Any, Self
 4
 5from plain import postgres
 6from plain.postgres import types
 7from plain.runtime import settings
 8from plain.utils import timezone
 9
10__all__ = ["CachedItem", "CachedItemQuerySet"]
11
12
13class CachedItemQuerySet(postgres.QuerySet["CachedItem"]):
14    def live(self) -> Self:
15        """Rows readable right now: never-expiring *or* not-yet-expired.
16
17        This is the filter cache reads use -- an entry past its `expires_at`
18        reads as absent. (Contrast `unexpired()`, which matches only rows with a
19        *future* expiry.)
20        """
21        return self.filter(
22            postgres.Q(expires_at__isnull=True)
23            | postgres.Q(expires_at__gte=timezone.now())
24        )
25
26    def expired(self) -> Self:
27        return self.filter(expires_at__lt=timezone.now())
28
29    def unexpired(self) -> Self:
30        return self.filter(expires_at__gte=timezone.now())
31
32    def forever(self) -> Self:
33        return self.filter(expires_at=None)
34
35
36@postgres.register_model
37class CachedItem(postgres.Model):
38    key = types.TextField(max_length=255)
39    value: Any = types.JSONField(required=False, allow_null=True)
40    expires_at = types.DateTimeField(required=False, allow_null=True)
41    created_at = types.DateTimeField(create_now=True)
42    updated_at = types.DateTimeField(create_now=True, update_now=True)
43
44    query: CachedItemQuerySet = CachedItemQuerySet()
45
46    model_options = postgres.Options(
47        indexes=[
48            postgres.Index(
49                name="plaincache_cacheditem_expires_at_idx", fields=["expires_at"]
50            ),
51        ],
52        constraints=[
53            postgres.UniqueConstraint(
54                fields=["key"], name="plaincache_cacheditem_unique_key"
55            ),
56        ],
57        storage_parameters={
58            "autovacuum_vacuum_scale_factor": settings.CACHE_AUTOVACUUM_SCALE_FACTOR,
59            "toast.autovacuum_vacuum_scale_factor": settings.CACHE_TOAST_AUTOVACUUM_SCALE_FACTOR,
60        },
61    )
62
63    def __str__(self) -> str:
64        return self.key