> $agents Agent payloads for the engine. */ public function handle( AvailabilityQuery $query, array $agents ): SlotCollection { if ( null !== $query->exclude_booking_id ) { return $this->engine->generate( $query, $agents ); } $key = $this->cache_key( $query ); $hit = ( $this->cache_get )( $key ); if ( $hit instanceof SlotCollection ) { return $hit; } $result = $this->engine->generate( $query, $agents ); ( $this->cache_set )( $key, $result, $this->ttl_seconds ); return $result; } /** * Build a cache key including the generation counter. * * @param AvailabilityQuery $query Availability query. */ private function cache_key( AvailabilityQuery $query ): string { $extras = []; foreach ( $query->selected_extras as $row ) { $extras[] = $row['extraId'] . 'x' . $row['quantity']; } sort( $extras ); $day = $query->range_start_utc->format( 'Y-m-d' ); return sprintf( 'bookline_avail_g%d_%d_%d_%s_%s_%s_%d_%s', ( $this->generation )(), $query->service_id, $query->duration_id, null === $query->agent_id ? 'any' : (string) $query->agent_id, null === $query->location_id ? 'any' : (string) $query->location_id, $day, $query->attendees, implode( ',', $extras ) ); } }