$state Serializable state array. * * @return void * @since 1.1.0 */ public function save(string $requestId, array $state): void { $state['updatedAt'] = time(); set_transient(self::PREFIX . $requestId, $state, self::TTL); } /** * Retrieves the progress state for a request. * * @param string $requestId The client-generated UUID. * * @return array|null Null when not found or expired. * @since 1.1.0 */ public function load(string $requestId): ?array { $data = get_transient(self::PREFIX . $requestId); return is_array($data) ? $data : null; } /** * Deletes the progress state for a request. * * @param string $requestId The client-generated UUID. * * @return void * @since 1.1.0 */ public function delete(string $requestId): void { delete_transient(self::PREFIX . $requestId); } /** * Flags an in-flight request as stop-requested. * * Written by the chat-stop REST endpoint from a separate PHP request; the * blocking chat request polls the flag between loop iterations. Uses the * same shared persistence caveats as the progress state above. * * @param string $requestId The client-generated UUID. * * @return void * @since 1.0.5 */ public function requestStop(string $requestId): void { set_transient(self::STOP_PREFIX . $requestId, time(), self::TTL); } /** * Checks whether a stop has been requested for a request. * * @param string $requestId The client-generated UUID. * * @return bool * @since 1.0.5 */ public function isStopRequested(string $requestId): bool { if ('' === $requestId) { return false; } // Transients can be served from a per-request runtime cache; the flag // is written by a different PHP request while this one is running, so // every cached trace must be dropped before each check. Without an // external object cache a miss also lands in the "notoptions" cache, // which would hide the flag for the rest of this request. $key = self::STOP_PREFIX . $requestId; wp_cache_delete($key, 'transient'); wp_cache_delete($key, 'transient_timeout'); wp_cache_delete('_transient_' . $key, 'options'); wp_cache_delete('_transient_timeout_' . $key, 'options'); wp_cache_delete('notoptions', 'options'); wp_cache_delete('alloptions', 'options'); return false !== get_transient(self::STOP_PREFIX . $requestId); } /** * Clears the stop flag for a request. * * @param string $requestId The client-generated UUID. * * @return void * @since 1.0.5 */ public function clearStop(string $requestId): void { delete_transient(self::STOP_PREFIX . $requestId); } }