Konwencje nazewnictwa OxPHP\Shared\*

Przestrzeń nazw OxPHP\Shared\* to API współbieżności na poziomie aplikacji: Atomic, Counter, Flag, Map, Channel, Mutex, Once, Pool. Nazwy metod podlegają jednemu zestawowi reguł, dzięki czemu użytkownicy mogą przewidzieć kształt API bez zaglądania do dokumentacji każdego typu z osobna.

Ten dokument stanowi kanoniczne źródło odniesienia. Nowe prymitywy oraz zmiany w istniejących MUSZĄ się do niego stosować.

Reguły

1. Odczyt wartości — get()

Konwencja PHP. Używana przez Map::get(), Counter::get(), Once::get().

Atomic::load(?Ordering $order = null) to celowy wyjątek: jego istnienie niesie argument uporządkowania, sygnalizując, że odczyt jest częścią kontraktu modelu pamięci, odrębnego od zwykłego gettera.

2. Zapis wartości — set(), store() dla typów atomowych

Map::set(), reset wartości Mutex (przez with), Once::getOrInit(). Atomic::store($value, ?Ordering) odzwierciedla load z tego samego powodu.

3. Liczba elementów — count(): int

Każdy kontener, który udostępnia swój bieżący rozmiar, robi to pod nazwą count(): int. Channel dodatkowo implementuje \Countable, więc count($ch) działa jako natywny idiom dla elementów w kolejce. Map i Pool udostępniają count(): int jako metodę, ale nie implementują \Countable — wywołaj ją bezpośrednio:

php
$ch = new OxPHP\Shared\Channel(1024); $map = new OxPHP\Shared\Map(); $pool = new OxPHP\Shared\Pool($factory); count($ch); // queued items (Channel implements \Countable) $map->count(); // entries $pool->count(); // total live slots (in-use + idle)

Żadnych size(), len() ani pending() — są one zakazane na publicznej powierzchni API, niezależnie od tego, z jakiego języka wywodzi się pamięć mięśniowa autora implementacji.

4. Getter logiczny — prefiks is*()

Channel::isClosed().

Żadnych gołych czasowników (test, check) ani nazw specyficznych dla domeny (closed). Prefiks is oznacza czysty odczyt właściwości logicznej.

Typ, którego stan jest bogatszy niż pojedyncza wartość logiczna, udostępnia go jako metodę status() zwracającą enum, zamiast gettera is*() — stosują się do tego RecvResult::status() z Channel oraz Once::status(): Once\Status (Uninitialized/Pending/Ready/Poisoned). Sięgnij po status(), gdy odpowiedź ma więcej niż dwa przypadki.

Mutex nie udostępnia isCorrupted() — uszkodzenie jest trwałe, nieodwracalne i ujawniane przez CorruptedMutexException przy kolejnym przejęciu. Z takiego sprawdzenia nie da się zrobić nic pożytecznego poza ponownym przejęciem i przechwyceniem wyjątku.

5. Trychotomia polityki oczekiwania — try* / goła nazwa / *Timeout

Prymitywy blokujące (Channel, Mutex) wyrażają politykę oczekiwania poprzez nazwę metody, a nie przez przeciążony argument ?float $timeout:

Przyrostek Zachowanie Przykłady
try* Nieblokująca; natychmiast zgłasza wariant niepowodzenia. Channel::trySend, Channel::tryRecv, Mutex::tryWithLock
(goła nazwa) Blokuje w nieskończoność (lub do anulowania Fibera żądania). Channel::send, Channel::recv, Mutex::withLock
*Timeout Ograniczone oczekiwanie. Przyjmuje obowiązkowy int $ms > 0. Channel::sendTimeout, Channel::recvTimeout, Mutex::withLockTimeout

Trychotomia przenosi trzy niejednoznaczne polityki (null = w nieskończoność, 0 = próba, wartość dodatnia = ograniczone) z jednego parametru do trzech metod o samodokumentujących się nazwach.

Note

Argument $ms w metodach *Timeout jest ściśle dodatni. Wartości zerowe, ujemne, niecałkowite oraz brakujące powodują zgłoszenie OxPHP\Shared\TypeException na moście.

Operacje warunkowego powodzenia znajdują się w Map pod nazwą setIfAbsent, a nie try*: Map::setIfAbsent zatwierdza zmianę tylko wtedy, gdy klucza brakowało, i zwraca bool (odpowiednik HashMap::try_insert). Nazwa setIfAbsent jest zarezerwowana dla tej jednej semantyki; nie używaj jej ponownie w innym miejscu.

Wspólny niezmiennik dla try*: albo zwraca wynik typu wartościowego (Result) dla Channel, albo rzuca ContentionException dla Mutex. Nigdy nie zwraca null na zakodowanie „nie powiodło się". Tak działało stare API i to ono rodziło niejednoznaczność operatora ?? (null-coalescing), którą trychotomia eliminuje.

6. Compare-and-swap — compareAndSet()

Atomic::compareAndSet(), Flag::compareAndSet(). Zawsze zwraca bool (zamiana nastąpiła albo nie).

7. Podmiana i zwrot poprzedniej wartości — swap()

Atomic::swap() dla wartości całkowitych, Flag::swap() dla wartości logicznych. Zwraca poprzednią wartość.

8. Atomowy RMW zwracający poprzednią wartość — prefiks fetch*()

Atomic::fetchAdd(), fetchSub(), fetchAnd(), fetchOr(), fetchXor().

Prefiks fetch koduje kontrakt zwracania: wartość sprzed operacji. Kontrastuje to z Counter::add(), który zwraca nową wartość (licznik agregujący w stylu LongAdder).

Przy dodawaniu nowych metod RMW najpierw wybierz kontrakt, a dopiero potem nazwę:

  • zwrot poprzedniej wartości → fetchVerb(args)
  • zwrot nowej wartości → goła verb(args)

Nie mieszaj tych konwencji.

9. Reset do wartości domyślnej — clear()

Map::clear() — opróżnia kontener; zwraca void.

Counter nie ma clear() — jego resetem okienkowym jest set(0). Counter::set() to udokumentowany wyjątek, który zwraca poprzednią wartość (a nie void): jest to atomowa wymiana, a set(0) odczytujący dotychczasową sumę to idiom sumThenReset z LongAdder. (Atomic zapisuje tę samą operację jako swap(); Counter zachowuje set, ponieważ set($n) czyta się naturalnie przy inicjalizacji i pracy okienkowej.)

10. Tożsamość w rejestrze — id(): int

Każda instancja Shared\* udostępnia id(): int na potrzeby logów oraz endpointu obserwowalności /__ox_shared/entry?id=<id>.

Ściąga

Koncepcja Nazwa kanoniczna Przykłady
Odczyt wartości get() Map::get, Counter::get
Odczyt typu atomowego load($order) Atomic::load
Zapis wartości set() Map::set
Zapis typu atomowego store($v, $order) Atomic::store
Liczba elementów count(): int Map::count, Channel::count, Pool::count
Właściwość logiczna is*(): bool Channel::isClosed
Wstawienie warunkowe setIfAbsent($k, $v) Map::setIfAbsent
Oczekiwanie nieblokujące try*() Channel::trySend, Mutex::tryWithLock
Oczekiwanie w nieskończoność goła nazwa czasownika Channel::send, Channel::recv, Mutex::withLock
Oczekiwanie ograniczone *Timeout(int $ms) Channel::sendTimeout, Mutex::withLockTimeout
Compare-and-swap compareAndSet() Atomic::compareAndSet
Podmiana, zwrot poprzedniej swap() Atomic::swap, Flag::swap
Atomowy RMW, zwrot poprzedniej fetch*() Atomic::fetchAdd
Atomowy RMW, zwrot nowej goła nazwa czasownika Counter::add
Reset do domyślnej clear() Map::clear
ID w rejestrze id(): int każdy typ Shared\*

Dodawanie nowego typu Shared\*

Proponując nowy prymityw, wypełnij tę listę kontrolną przed scaleniem:

  • Każda metoda odpowiada wierszowi w ściądze albo ma ADR wyjaśniający wyjątek (zobacz Atomic::load/store oraz Counter::set powyżej).
  • Jeśli typ przechowuje kolekcję wartości, implementuje \Countable i udostępnia count(): int.
  • Metody odczytu to get lub load (tylko dla typów atomowych).
  • Gettery logiczne używają prefiksu is*.
  • Warianty polityki oczekiwania są zgodne z trychotomią try* / goła nazwa / *Timeout(int $ms). Wariant *Timeout przyjmuje int $ms > 0 i odrzuca wartości zerowe / ujemne / niecałkowite z TypeException. Metody polityki oczekiwania try* zwracają albo wynik typu wartościowego (Result), albo rzucają wyjątek domenowy — nigdy nie kodują tego przez null. Operacje warunkowego powodzenia stosują dedykowane nazewnictwo setIfAbsent zamiast try*.
  • Żadnych len, size, pending, test ani innych doraźnych nazw.
  • Czasowniki specyficzne dla domeny (evict, drain, flush itp.) pojawiają się tylko wtedy, gdy żaden kanoniczny wpis w ściądze nie obejmuje danej koncepcji.

Nazwy obserwowalności pozostają w tyle za API PHP

Powierzchnia skierowana do operatorów — nazwy metryk Prometheusa oraz JSON pod /__ox_shared/entry?id=<id> — to kontrakt odrębny od API PHP. Zmiana tych nazw psuje pulpity i reguły alertów. Aby uniknąć cichej niespójności, objęte tym nazwy są emitowane dwukrotnie przez jeden cykl wydawniczy:

Powierzchnia Przestarzała (nadal emitowana) Kanoniczna
Prometheus oxphp_shared_channel_pending oxphp_shared_channel_count
Prometheus oxphp_shared_pool_size oxphp_shared_pool_count
Wpis JSON Channel.pending Channel.count
Wpis JSON Pool.size Pool.count

Wiersze # HELP przestarzałych metryk noszą prefiks (deprecated, removed in a future release; use *_count), a wtyczka ox_shared emituje przy starcie WARN, gdy tylko włączona jest introspekcja lub metryki.

Migracja

Przenieś pulpity i reguły alertów na nazwy z _count, zanim zakończy się cykl wycofywania. Po usunięciu emitowane będą wyłącznie nazwy kanoniczne, a panele Prometheusa/Grafany odwołujące się do starych zaczną zwracać puste serie.

Stabilność

Reguły te są częścią kontraktu OxPHP\Shared\* 1.0. Po wydaniu 1.0 zmiany nazw stają się zmianami łamiącymi kompatybilność i wymagają cyklu wycofywania. Przed 1.0 reguły również obowiązują — nowe metody, które je naruszają, zostaną odrzucone podczas przeglądu.