From ef4dfd0ae8e5c5eb18abaa126e33ac197903c877 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Thu, 23 Jul 2026 12:52:16 +0300 Subject: [PATCH] =?UTF-8?q?feat(=D1=81=D0=BC=D1=81):=20=D1=82=D0=BE=D1=87?= =?UTF-8?q?=D0=BA=D0=B0=20=D1=80=D0=B0=D1=81=D1=88=D0=B8=D1=80=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20=D1=80=D0=B5=D0=B7=D0=B5=D1=80=D0=B2=D0=B0=20?= =?UTF-8?q?=D0=BA=D0=B0=D0=BD=D0=B0=D0=BB=D0=B0=20(=D1=84=D0=BB=D0=B0?= =?UTF-8?q?=D0=B3,=20=D0=BF=D0=BE=20=D1=83=D0=BC=D0=BE=D0=BB=D1=87=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D1=8E=20=D0=B2=D1=8B=D0=BA=D0=BB)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/app/Services/Sms/SmsRouter.php | 23 ++++++++ app/tests/Unit/Sms/SmsRouterFailoverTest.php | 57 ++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 app/tests/Unit/Sms/SmsRouterFailoverTest.php diff --git a/app/app/Services/Sms/SmsRouter.php b/app/app/Services/Sms/SmsRouter.php index b8f6255f..2add1296 100644 --- a/app/app/Services/Sms/SmsRouter.php +++ b/app/app/Services/Sms/SmsRouter.php @@ -42,4 +42,27 @@ final class SmsRouter return $candidates[0]; } + + /** + * Запасной канал, если основной отказал. Работает ТОЛЬКО при включённом + * флаге services.sms.failover_to_universal (по умолчанию ВЫКЛ). Возвращает + * универсала, отличного от основного. Точка расширения — сейчас не вызывается + * из джоба (решение владельца 23.07.2026 — без резерва). + */ + public function fallbackFor(string $operator): ?SmsProvider + { + if (! config('services.sms.failover_to_universal')) { + return null; + } + + $primary = $this->pick($operator); + + foreach ($this->providers as $provider) { + if (in_array('*', $provider->servesOperators(), true) && $provider !== $primary) { + return $provider; + } + } + + return null; + } } diff --git a/app/tests/Unit/Sms/SmsRouterFailoverTest.php b/app/tests/Unit/Sms/SmsRouterFailoverTest.php new file mode 100644 index 00000000..cc64a946 --- /dev/null +++ b/app/tests/Unit/Sms/SmsRouterFailoverTest.php @@ -0,0 +1,57 @@ +k; + } + + public function servesOperators(): array + { + return $this->ops; + } + + public function priceKopecks(string $operator): int + { + return 100; + } + + public function send(SmsOutgoing $m): SmsSendResult + { + return new SmsSendResult('x', 1, 100, CarbonImmutable::now()); + } + }; +} + +it('по умолчанию резерва нет — второй канал не отдаётся', function () { + config()->set('services.sms.failover_to_universal', false); + $router = new SmsRouter([ + failover_provider('mts', ['mts']), + failover_provider('smsc', ['*']), + ]); + + expect($router->fallbackFor('mts'))->toBeNull(); +}); + +it('при включённом флаге резерв — универсал', function () { + config()->set('services.sms.failover_to_universal', true); + $router = new SmsRouter([ + failover_provider('mts', ['mts']), + failover_provider('smsc', ['*']), + ]); + + expect($router->fallbackFor('mts')?->key())->toBe('smsc'); +});