$products Products in upstream order. */ public function replaceCategory( string $searchIndex, array $products ): int; /** * Atomically replace one brand snapshot. * * @param string $brand Priority brand. * @param list $products Products in upstream order. */ public function replaceBrand( string $brand, array $products ): int; /** * Delete one brand snapshot. * * @param string $brand Priority brand. */ public function deleteBrand( string $brand ): void; /** * Load grouped rows for shortcode rendering. * * @param list $categories Category order. * @param string $sort Closed sort token. * @param int $perCategory Maximum rows per category. * * @return array> */ public function findGrouped( array $categories, string $sort, int $perCategory ): array; /** * Load matching product brands, filtering stale mismatches before limiting. * * @param list $brands Brand order. * @param string $sort Closed sort token. * @param int $perBrand Maximum rows per brand. * * @return array> */ public function findBrandsGrouped( array $brands, string $sort, int $perBrand ): array; /** * Count all stored discount products. */ public function count(): int; /** * Return the newest upstream fetch timestamp. */ public function latestFetchedAt(): ?DateTimeImmutable; }