fastcache-ai 1.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,191 @@
1
+ """FastCache — a zero-infrastructure cache for AI workloads.
2
+
3
+ Installed as ``fastcache-ai``, imported as ``fastcache_ai``. The import name carries the suffix
4
+ because the bare ``fastcache`` name on PyPI already belongs to an unrelated C implementation of
5
+ ``functools.lru_cache``; sharing it would make the two packages overwrite each other on disk.
6
+
7
+ .. code-block:: python
8
+
9
+ from fastcache_ai import fastcache
10
+
11
+ @fastcache(ttl="15m")
12
+ def embed(prompt: str):
13
+ return model.encode(prompt)
14
+
15
+ Importing this package starts a background thread that locates or boots the Java engine. The import itself
16
+ never blocks and never raises: if no JVM can be found, the decorator degrades to calling your function, and
17
+ the reason is available from :func:`info`.
18
+
19
+ Set ``FASTCACHE_AUTOSTART=0`` to skip the background warm-up; the sidecar will then be started lazily on
20
+ first cache use instead.
21
+ """
22
+
23
+ from __future__ import annotations
24
+
25
+ import logging
26
+ import os
27
+ import threading
28
+ from typing import Any, Dict, Optional
29
+
30
+ from .bootstrap import console_url, ensure_sidecar, shutdown_sidecar
31
+ from .client import FastCacheClient
32
+ from .codec import Codec, describe_capabilities
33
+ from .decorator import build_key, default_client, fastcache, set_default_client, single_flight_stats
34
+ from .errors import (
35
+ FastCacheError,
36
+ ProtocolError,
37
+ SerializationError,
38
+ SidecarStartupError,
39
+ SidecarUnavailable,
40
+ WriteRejected,
41
+ )
42
+ from .l1 import HotKeyCache, NullL1
43
+ from .ttl import format_ttl, parse_ttl
44
+
45
+ __version__ = "1.1.0"
46
+
47
+ __all__ = [
48
+ "fastcache",
49
+ "FastCacheClient",
50
+ "HotKeyCache",
51
+ "NullL1",
52
+ "Codec",
53
+ "FastCacheError",
54
+ "SidecarUnavailable",
55
+ "SidecarStartupError",
56
+ "ProtocolError",
57
+ "WriteRejected",
58
+ "SerializationError",
59
+ "get",
60
+ "put",
61
+ "set",
62
+ "delete",
63
+ "stats",
64
+ "flush",
65
+ "ping",
66
+ "info",
67
+ "configure",
68
+ "ensure_sidecar",
69
+ "shutdown_sidecar",
70
+ "console_url",
71
+ "dashboard",
72
+ "single_flight_stats",
73
+ "default_client",
74
+ "set_default_client",
75
+ "build_key",
76
+ "parse_ttl",
77
+ "format_ttl",
78
+ "__version__",
79
+ ]
80
+
81
+ log = logging.getLogger("fastcache")
82
+
83
+ _startup_error: Optional[BaseException] = None
84
+ _startup_thread: Optional[threading.Thread] = None
85
+
86
+
87
+ # ---------------------------------------------------------------------------------------------------
88
+ # Module-level convenience API
89
+ # ---------------------------------------------------------------------------------------------------
90
+
91
+ def get(key: str, default: Any = None) -> Any:
92
+ """Reads a value from the shared client."""
93
+ return default_client().get(key, default)
94
+
95
+
96
+ def put(key: str, value: Any, ttl: Any = None) -> int:
97
+ """Writes a value through the shared client. Returns the wire status (0 = stored)."""
98
+ return default_client().put(key, value, ttl=ttl)
99
+
100
+
101
+ #: Redis-style alias for :func:`put`.
102
+ set = put # noqa: A001 - shadowing the builtin is intentional and scoped to this module's namespace
103
+
104
+
105
+ def delete(key: str) -> bool:
106
+ return default_client().delete(key)
107
+
108
+
109
+ def stats() -> Dict[str, Any]:
110
+ """Engine, L1 and client telemetry."""
111
+ return default_client().stats()
112
+
113
+
114
+ def flush() -> int:
115
+ """Drops every cached entry. Mostly useful between test cases."""
116
+ return default_client().flush()
117
+
118
+
119
+ def ping() -> bool:
120
+ return default_client().ping()
121
+
122
+
123
+ def configure(**kwargs: Any) -> FastCacheClient:
124
+ """Replaces the shared client with one built from ``kwargs``.
125
+
126
+ .. code-block:: python
127
+
128
+ fastcache.configure(host="10.0.0.5", port=7431, timeout=2.0)
129
+ fastcache.configure(l1=fastcache.NullL1()) # disable local caching entirely
130
+ """
131
+ client = FastCacheClient(**kwargs)
132
+ set_default_client(client)
133
+ return client
134
+
135
+
136
+ def dashboard(open_browser: bool = False) -> Optional[str]:
137
+ """Returns the management console URL, optionally opening it.
138
+
139
+ .. code-block:: python
140
+
141
+ fastcache.dashboard(open_browser=True) # live savings, memory and hit-rate console
142
+
143
+ Returns None when the console is disabled (``FASTCACHE_METRICS_PORT=off``) or its port was already
144
+ taken — the cache itself is unaffected either way.
145
+ """
146
+ ensure_sidecar()
147
+ url = console_url()
148
+ if url and open_browser:
149
+ import webbrowser
150
+
151
+ webbrowser.open(url)
152
+ return url
153
+
154
+
155
+ def info() -> Dict[str, Any]:
156
+ """Everything needed to diagnose a FastCache problem in one call."""
157
+ from . import bootstrap
158
+
159
+ details = bootstrap.info()
160
+ details["version"] = __version__
161
+ details["codecs"] = describe_capabilities()
162
+ details["autostart_error"] = repr(_startup_error) if _startup_error else None
163
+ details["single_flight"] = single_flight_stats()
164
+ return details
165
+
166
+
167
+ # ---------------------------------------------------------------------------------------------------
168
+ # Import-time autopilot
169
+ # ---------------------------------------------------------------------------------------------------
170
+
171
+ def _autostart() -> None:
172
+ """Warms the sidecar in the background.
173
+
174
+ Running on a daemon thread is the point: booting a JVM takes a few hundred milliseconds, and an
175
+ ``import`` that blocks that long is one people work around. By the time the first cache call arrives,
176
+ the engine is usually already up; if it is not, the call resolves it synchronously.
177
+
178
+ Failures are recorded, never raised. A missing JDK on a developer laptop must not break
179
+ ``import fastcache_ai`` at the top of a training script.
180
+ """
181
+ global _startup_error
182
+ try:
183
+ ensure_sidecar()
184
+ except BaseException as exc: # noqa: BLE001 - an import must not be able to fail here
185
+ _startup_error = exc
186
+ log.debug("fastcache: sidecar autostart deferred (%s)", exc)
187
+
188
+
189
+ if os.environ.get("FASTCACHE_AUTOSTART", "1").lower() not in {"0", "false", "no"}:
190
+ _startup_thread = threading.Thread(target=_autostart, name="fastcache-autostart", daemon=True)
191
+ _startup_thread.start()
Binary file