feat: add psagentai agent with deployment and configuration
Initial project setup including the main agent script, configuration files, profile JSON state, systemd service unit, startup script, deployment documentation, and Python dependencies. Includes .env, venv/, and __pycache__/ which should likely be excluded via .gitignore to avoid committing secrets and artifacts.
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import threading
|
||||
|
||||
|
||||
class _HTTP2ProbeCache:
|
||||
__slots__ = (
|
||||
"_lock",
|
||||
"_cache_locks",
|
||||
"_cache_values",
|
||||
)
|
||||
|
||||
def __init__(self) -> None:
|
||||
self._lock = threading.Lock()
|
||||
self._cache_locks: dict[tuple[str, int], threading.RLock] = {}
|
||||
self._cache_values: dict[tuple[str, int], bool | None] = {}
|
||||
|
||||
def acquire_and_get(self, host: str, port: int) -> bool | None:
|
||||
# By the end of this block we know that
|
||||
# _cache_[values,locks] is available.
|
||||
value = None
|
||||
with self._lock:
|
||||
key = (host, port)
|
||||
try:
|
||||
value = self._cache_values[key]
|
||||
# If it's a known value we return right away.
|
||||
if value is not None:
|
||||
return value
|
||||
except KeyError:
|
||||
self._cache_locks[key] = threading.RLock()
|
||||
self._cache_values[key] = None
|
||||
|
||||
# If the value is unknown, we acquire the lock to signal
|
||||
# to the requesting thread that the probe is in progress
|
||||
# or that the current thread needs to return their findings.
|
||||
key_lock = self._cache_locks[key]
|
||||
key_lock.acquire()
|
||||
try:
|
||||
# If the by the time we get the lock the value has been
|
||||
# updated we want to return the updated value.
|
||||
value = self._cache_values[key]
|
||||
|
||||
# In case an exception like KeyboardInterrupt is raised here.
|
||||
except BaseException as e: # Defensive:
|
||||
assert not isinstance(e, KeyError) # KeyError shouldn't be possible.
|
||||
key_lock.release()
|
||||
raise
|
||||
|
||||
return value
|
||||
|
||||
def set_and_release(
|
||||
self, host: str, port: int, supports_http2: bool | None
|
||||
) -> None:
|
||||
key = (host, port)
|
||||
key_lock = self._cache_locks[key]
|
||||
with key_lock: # Uses an RLock, so can be locked again from same thread.
|
||||
if supports_http2 is None and self._cache_values[key] is not None:
|
||||
raise ValueError(
|
||||
"Cannot reset HTTP/2 support for origin after value has been set."
|
||||
) # Defensive: not expected in normal usage
|
||||
|
||||
self._cache_values[key] = supports_http2
|
||||
key_lock.release()
|
||||
|
||||
def _values(self) -> dict[tuple[str, int], bool | None]:
|
||||
"""This function is for testing purposes only. Gets the current state of the probe cache"""
|
||||
with self._lock:
|
||||
return {k: v for k, v in self._cache_values.items()}
|
||||
|
||||
def _reset(self) -> None:
|
||||
"""This function is for testing purposes only. Reset the cache values"""
|
||||
with self._lock:
|
||||
self._cache_locks = {}
|
||||
self._cache_values = {}
|
||||
|
||||
|
||||
_HTTP2_PROBE_CACHE = _HTTP2ProbeCache()
|
||||
|
||||
set_and_release = _HTTP2_PROBE_CACHE.set_and_release
|
||||
acquire_and_get = _HTTP2_PROBE_CACHE.acquire_and_get
|
||||
_values = _HTTP2_PROBE_CACHE._values
|
||||
_reset = _HTTP2_PROBE_CACHE._reset
|
||||
|
||||
__all__ = [
|
||||
"set_and_release",
|
||||
"acquire_and_get",
|
||||
]
|
||||
Reference in New Issue
Block a user