added test for channel 2

This commit is contained in:
2026-07-07 16:35:14 +03:30
parent 3ff11dcd75
commit 1f75f5986f
3 changed files with 47 additions and 10 deletions
+3 -5
View File
@@ -86,12 +86,10 @@ class LivePriceTickService
app(LivePriceCacheService::class)->markTick(); app(LivePriceCacheService::class)->markTick();
// last از put داخل lastPrice؛ list بعد از sync محصولات // last از put داخل lastPrice؛ list بعد از sync محصولات
$listChanged = app(PriceBroadcastService::class)->broadcastListIfChanged(); app(PriceBroadcastService::class)->broadcastListIfChanged();
// بعد از هر تغییر قیمت، قیمت‌ها را به کانال‌های پیام‌رسان بفرست (با cooldown داخلی) // ارسال قیمت به کانال‌ها — مستقل از SSE؛ تشخیص تغییر قیمت + cooldown داخل سرویس است
if ($listChanged) { app(PriceChannelBroadcastService::class)->broadcastIfEligible();
app(PriceChannelBroadcastService::class)->broadcastIfEligible();
}
} finally { } finally {
$lock->release(); $lock->release();
} }
+43 -4
View File
@@ -20,6 +20,8 @@ class PriceChannelBroadcastService
{ {
private const COOLDOWN_CACHE_KEY = 'price_channel:last_sent_at'; private const COOLDOWN_CACHE_KEY = 'price_channel:last_sent_at';
private const SIGNATURE_CACHE_KEY = 'price_channel:last_signature';
private const SUPPORTED_MESSENGERS = ['bale', 'telegram', 'rubika']; private const SUPPORTED_MESSENGERS = ['bale', 'telegram', 'rubika'];
/** مثقال بازار آبشده (گرم) — وقتی تنظیم change_mesghal خالی باشد */ /** مثقال بازار آبشده (گرم) — وقتی تنظیم change_mesghal خالی باشد */
@@ -42,6 +44,19 @@ class PriceChannelBroadcastService
$targets = $this->resolveActiveTargets(); $targets = $this->resolveActiveTargets();
if ($targets === []) { if ($targets === []) {
Log::debug('PriceChannel: enabled ولی هیچ مقصد فعالی نیست (توکن/مقصد را چک کن)');
return;
}
$products = $this->eligibleProducts();
if ($products === []) {
Log::debug('PriceChannel: محصول واجد شرایطی نیست (active/قیمت/ساعت کاری)');
return;
}
// فقط وقتی قیمت واقعاً تغییر کرده باشد
$signature = $this->priceSignature($products);
if ($signature === Cache::get(self::SIGNATURE_CACHE_KEY)) {
return; return;
} }
@@ -49,21 +64,41 @@ class PriceChannelBroadcastService
return; return;
} }
$message = $this->buildMessage(); $message = $this->buildMessage($products);
if ($message === '') { if ($message === '') {
return; return;
} }
$results = [];
foreach ($targets as $messenger => $target) { foreach ($targets as $messenger => $target) {
$this->dispatchToMessenger($messenger, $target['token'], $target['chat_ids'], $message); $results[$messenger] = $this->dispatchToMessenger($messenger, $target['token'], $target['chat_ids'], $message);
} }
$this->markSent(); $this->markSent();
Cache::put(self::SIGNATURE_CACHE_KEY, $signature, now()->addDay());
Log::info('PriceChannel: قیمت به کانال ارسال شد', [
'targets' => array_keys($targets),
'products' => count($products),
'results' => $results,
]);
} catch (\Throwable $e) { } catch (\Throwable $e) {
Log::warning('PriceChannelBroadcast failed', ['message' => $e->getMessage()]); Log::warning('PriceChannelBroadcast failed', ['message' => $e->getMessage()]);
} }
} }
/** امضای قیمت محصولات واجد شرایط — برای تشخیص تغییر قیمت */
private function priceSignature(array $products): string
{
$parts = [];
foreach ($products as $product) {
$parts[] = $product->id . ':' . (int) ($product->price ?? 0)
. ':' . ((int) ($product->open_buy)) . ((int) ($product->open_sell));
}
return md5(implode('|', $parts));
}
/** /**
* ارسال دستی (عیب‌یابی) — cooldown و شرط تغییر قیمت را نادیده می‌گیرد. * ارسال دستی (عیب‌یابی) — cooldown و شرط تغییر قیمت را نادیده می‌گیرد.
* وضعیت روشن/خاموش، انتخاب پیام‌رسان، توکن و مقصد همچنان لازم است. * وضعیت روشن/خاموش، انتخاب پیام‌رسان، توکن و مقصد همچنان لازم است.
@@ -84,6 +119,10 @@ class PriceChannelBroadcastService
if ($message !== '' && $targets !== []) { if ($message !== '' && $targets !== []) {
$this->markSent(); $this->markSent();
$products = $this->eligibleProducts();
if ($products !== []) {
Cache::put(self::SIGNATURE_CACHE_KEY, $this->priceSignature($products), now()->addDay());
}
} }
return [ return [
@@ -185,9 +224,9 @@ class PriceChannelBroadcastService
/** /**
* ساخت متن پیام قیمت — مرتب و بر اساس داده‌ی هر محصول. * ساخت متن پیام قیمت — مرتب و بر اساس داده‌ی هر محصول.
*/ */
public function buildMessage(): string public function buildMessage(?array $products = null): string
{ {
$products = $this->eligibleProducts(); $products = $products ?? $this->eligibleProducts();
if ($products === []) { if ($products === []) {
return ''; return '';
} }
+1 -1
View File
@@ -51,7 +51,7 @@ return [
'stack' => [ 'stack' => [
'driver' => 'stack', 'driver' => 'stack',
'channels' => ['single'], 'channels' => ['daily'],
'ignore_exceptions' => false, 'ignore_exceptions' => false,
], ],