|
84074
|
2899
|
2
|
2026-05-28T11:23:06.507103+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967386507_m1.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-024 github.com/jiminny/app/pull/12130/changes#diff-024e2701f53cba09fb2fd8e644d1107959e8598b1d182b1ad5876d5673e73059...
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:
Structural and Dependency Changes
Structural and Dependency Changes
Replaced Datadog:
Removed the
ChaseConey\LaravelDatadogHelper\Datadog
dependency and replaced it with
Jiminny\Component\ES\ReindexTargetStatsReporter
.
Added Constants and Properties:
Introduced a new
ENVIRONMENT
constant (set to
'testing'
) and a
$statsReporter
property to hold the mock for the new stats reporter....
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"AI Chat settings","depth":3,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":3,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Main menu","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open mode picker, currently 3.1 Pro","depth":6,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Gemini","depth":13,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"3.1 Pro","depth":11,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Chat","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open menu for conversation actions.","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Conversation with Gemini","depth":7,"on_screen":true,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Conversation with Gemini","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":13,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"You said","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.","depth":15,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Expand","depth":13,"on_screen":false,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Copy prompt","depth":12,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Gemini said","depth":12,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Gemini said","depth":13,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Here is a summary of the changes in the provided git diff for","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"UpdateProcessManagerTest.php","depth":17,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":":","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Structural and Dependency Changes","depth":15,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Structural and Dependency Changes","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Replaced Datadog:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Removed the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ChaseConey\\LaravelDatadogHelper\\Datadog","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"dependency and replaced it with","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Jiminny\\Component\\ES\\ReindexTargetStatsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":".","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Added Constants and Properties:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Introduced a new","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ENVIRONMENT","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"constant (set to","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"'testing'","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":") and a","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"$statsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"property to hold the mock for the new stats reporter.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
4179630964884368970
|
-3250018833119285116
|
idle
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:
Structural and Dependency Changes
Structural and Dependency Changes
Replaced Datadog:
Removed the
ChaseConey\LaravelDatadogHelper\Datadog
dependency and replaced it with
Jiminny\Component\ES\ReindexTargetStatsReporter
.
Added Constants and Properties:
Introduced a new
ENVIRONMENT
constant (set to
'testing'
) and a
$statsReporter
property to hold the mock for the new stats reporter....
|
NULL
|
NULL
|
NULL
|
NULL
|
|
84073
|
2900
|
6
|
2026-05-28T11:22:55.190188+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967375190_m2.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-024 github.com/jiminny/app/pull/12130/changes#diff-024e2701f53cba09fb2fd8e644d1107959e8598b1d182b1ad5876d5673e73059...
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:
Structural and Dependency Changes
Structural and Dependency Changes
Replaced Datadog:
Removed the
ChaseConey\LaravelDatadogHelper\Datadog
dependency and replaced it with
Jiminny\Component\ES\ReindexTargetStatsReporter
.
Added Constants and Properties:
Introduced a new
ENVIRONMENT
constant (set to
'testing'
) and a
$statsReporter
property to hold the mock for the new stats reporter.
Processor Instantiation:
Updated the
getProcessor()
method to inject the new
$statsReporter
mock into the
UpdateProcessManager
and utilize the
ENVIRONMENT
constant.
Test Case Modifications
Test Case Modifications
Removed Memory Logging Tests:
Deleted
testLogMemoryUsageEmitsGaugeWhenLockIsAbsent
and
testLogMemoryUsageSkipsGaugeWhenLockIsPresent
entirely, as the Redis lock and Datadog gauge logic were removed.
Added Empty Selection Test:
Introduced
testEmptySelectionLogsAndReturnsFalse
to verify that processing an empty selection logs a debug message, skips batch manager operations (
generateName
,
scheduleWork
,
finishWork
), skips the stats reporter, and cleanly returns
false
.
Updated Existing Tests:
Modified
testRunUpdate
and
testRunDoUpdateButThrottled
to assert that the
$statsReporter->report()
method is called and to utilize the updated status manager mock.
Helper Method Refactoring
Helper Method Refactoring
Dynamic Status Manager Assertions:
Updated the
prepareStatusManager(int $invokeTimes = 0)
method to accept an integer. This allows tests to dynamically assert exactly how many times methods like
generateName
,
setUpdateTarget
,
scheduleWork
, and
finishWork
are invoked.
Removed Obsolete Helpers:
Deleted the
prepareLogger()
and
silenceDatadogAndRedisLock()
helper methods, replacing their inline functionality with standard
Log::shouldReceive
expectations where needed.
Good response
Bad response
Share & export
Copy
Show more options
You said find potential issues
You said
find potential issues
Copy prompt
Gemini said
Gemini said
Based on the provided git diff of
UpdateProcessManagerTest.php
, here are the potential issues, risks, and improvements identified in the changes:
1. Missing setUpdateTarget Expectation in testEmptySelectionLogsAndReturnsFalse
1. Missing
setUpdateTarget
Expectation in
testEmptySelectionLogsAndReturnsFalse
In the newly added test
testEmptySelectionLogsAndReturnsFalse...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.11402926,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.27055067,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.28172386,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.37988827,"width":0.09740692,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"bounds":{"left":0.0,"top":0.40143654,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.41260973,"width":0.08543883,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.43415803,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.44533122,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0,"top":0.4668795,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.47805268,"width":0.10106383,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"bounds":{"left":0.0028257978,"top":0.5047885,"width":0.036070477,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0028257978,"top":0.528332,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015957447,"top":0.5395052,"width":0.013297873,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.0028257978,"top":0.56105345,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"bounds":{"left":0.015957447,"top":0.57222664,"width":0.1271609,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.5937749,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.6049481,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.62649643,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.63766956,"width":0.12134308,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.6592179,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.6703911,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.69193935,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.70311254,"width":0.18201463,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.06732048,"top":0.69912213,"width":0.007978723,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.0028257978,"top":0.72625697,"width":0.07413564,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"bounds":{"left":0.0028257978,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"bounds":{"left":0.013796543,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"bounds":{"left":0.024933511,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"bounds":{"left":0.036070477,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"bounds":{"left":0.04720745,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"AI Chat settings","depth":3,"bounds":{"left":0.35854387,"top":0.055067837,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":3,"bounds":{"left":0.37051198,"top":0.055067837,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Main menu","depth":5,"bounds":{"left":0.08228058,"top":0.09736632,"width":0.015957447,"height":0.03830806},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open mode picker, currently 3.1 Pro","depth":6,"bounds":{"left":0.09823803,"top":0.10694334,"width":0.047539894,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Gemini","depth":13,"bounds":{"left":0.1022274,"top":0.10853951,"width":0.017121011,"height":0.016360734},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"3.1 Pro","depth":11,"bounds":{"left":0.12084442,"top":0.10853951,"width":0.013796543,"height":0.015961692},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Chat","depth":5,"bounds":{"left":0.35854387,"top":0.10215483,"width":0.011968086,"height":0.028731046},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open menu for conversation actions.","depth":5,"bounds":{"left":0.37051198,"top":0.10215483,"width":0.011968086,"height":0.028731046},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Conversation with Gemini","depth":7,"bounds":{"left":0.079288565,"top":0.14445332,"width":0.0003324468,"height":0.0007980846},"on_screen":true,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Conversation with Gemini","depth":8,"bounds":{"left":0.079288565,"top":0.14684756,"width":0.1200133,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":13,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"You said","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.","depth":15,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Expand","depth":13,"on_screen":false,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Copy prompt","depth":12,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Gemini said","depth":12,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Gemini said","depth":13,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Here is a summary of the changes in the provided git diff for","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"UpdateProcessManagerTest.php","depth":17,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":":","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Structural and Dependency Changes","depth":15,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Structural and Dependency Changes","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Replaced Datadog:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Removed the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ChaseConey\\LaravelDatadogHelper\\Datadog","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"dependency and replaced it with","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Jiminny\\Component\\ES\\ReindexTargetStatsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":".","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Added Constants and Properties:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Introduced a new","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ENVIRONMENT","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"constant (set to","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"'testing'","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":") and a","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"$statsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"property to hold the mock for the new stats reporter.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Processor Instantiation:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Updated the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"getProcessor()","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"method to inject the new","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"$statsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"mock into the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"UpdateProcessManager","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"and utilize the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ENVIRONMENT","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"constant.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Test Case Modifications","depth":15,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Test Case Modifications","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Removed Memory Logging Tests:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Deleted","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testLogMemoryUsageEmitsGaugeWhenLockIsAbsent","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"and","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testLogMemoryUsageSkipsGaugeWhenLockIsPresent","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"entirely, as the Redis lock and Datadog gauge logic were removed.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Added Empty Selection Test:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Introduced","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testEmptySelectionLogsAndReturnsFalse","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"to verify that processing an empty selection logs a debug message, skips batch manager operations (","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"generateName","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":",","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"scheduleWork","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":",","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"finishWork","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"), skips the stats reporter, and cleanly returns","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"false","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":".","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Updated Existing Tests:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Modified","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testRunUpdate","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"and","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testRunDoUpdateButThrottled","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"to assert that the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"$statsReporter->report()","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"method is called and to utilize the updated status manager mock.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Helper Method Refactoring","depth":15,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Helper Method Refactoring","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Dynamic Status Manager Assertions:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Updated the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"prepareStatusManager(int $invokeTimes = 0)","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"method to accept an integer. This allows tests to dynamically assert exactly how many times methods like","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"generateName","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":",","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"setUpdateTarget","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":",","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"scheduleWork","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":", and","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"finishWork","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"are invoked.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Removed Obsolete Helpers:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Deleted the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"prepareLogger()","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"and","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"silenceDatadogAndRedisLock()","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"helper methods, replacing their inline functionality with standard","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Log::shouldReceive","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"expectations where needed.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXCheckBox","text":"Good response","depth":15,"on_screen":false,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Bad response","depth":15,"on_screen":false,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Share & export","depth":14,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Copy","depth":15,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Show more options","depth":14,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"You said find potential issues","depth":13,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"You said","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"find potential issues","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Copy prompt","depth":12,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Gemini said","depth":12,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Gemini said","depth":13,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Based on the provided git diff of","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"UpdateProcessManagerTest.php","depth":17,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":", here are the potential issues, risks, and improvements identified in the changes:","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"1. Missing setUpdateTarget Expectation in testEmptySelectionLogsAndReturnsFalse","depth":15,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"1. Missing","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"setUpdateTarget","depth":17,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Expectation in","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testEmptySelectionLogsAndReturnsFalse","depth":17,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"In the newly added test","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testEmptySelectionLogsAndReturnsFalse","depth":17,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
-7108448609540925913
|
-3114347894345797500
|
idle
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:
Structural and Dependency Changes
Structural and Dependency Changes
Replaced Datadog:
Removed the
ChaseConey\LaravelDatadogHelper\Datadog
dependency and replaced it with
Jiminny\Component\ES\ReindexTargetStatsReporter
.
Added Constants and Properties:
Introduced a new
ENVIRONMENT
constant (set to
'testing'
) and a
$statsReporter
property to hold the mock for the new stats reporter.
Processor Instantiation:
Updated the
getProcessor()
method to inject the new
$statsReporter
mock into the
UpdateProcessManager
and utilize the
ENVIRONMENT
constant.
Test Case Modifications
Test Case Modifications
Removed Memory Logging Tests:
Deleted
testLogMemoryUsageEmitsGaugeWhenLockIsAbsent
and
testLogMemoryUsageSkipsGaugeWhenLockIsPresent
entirely, as the Redis lock and Datadog gauge logic were removed.
Added Empty Selection Test:
Introduced
testEmptySelectionLogsAndReturnsFalse
to verify that processing an empty selection logs a debug message, skips batch manager operations (
generateName
,
scheduleWork
,
finishWork
), skips the stats reporter, and cleanly returns
false
.
Updated Existing Tests:
Modified
testRunUpdate
and
testRunDoUpdateButThrottled
to assert that the
$statsReporter->report()
method is called and to utilize the updated status manager mock.
Helper Method Refactoring
Helper Method Refactoring
Dynamic Status Manager Assertions:
Updated the
prepareStatusManager(int $invokeTimes = 0)
method to accept an integer. This allows tests to dynamically assert exactly how many times methods like
generateName
,
setUpdateTarget
,
scheduleWork
, and
finishWork
are invoked.
Removed Obsolete Helpers:
Deleted the
prepareLogger()
and
silenceDatadogAndRedisLock()
helper methods, replacing their inline functionality with standard
Log::shouldReceive
expectations where needed.
Good response
Bad response
Share & export
Copy
Show more options
You said find potential issues
You said
find potential issues
Copy prompt
Gemini said
Gemini said
Based on the provided git diff of
UpdateProcessManagerTest.php
, here are the potential issues, risks, and improvements identified in the changes:
1. Missing setUpdateTarget Expectation in testEmptySelectionLogsAndReturnsFalse
1. Missing
setUpdateTarget
Expectation in
testEmptySelectionLogsAndReturnsFalse
In the newly added test
testEmptySelectionLogsAndReturnsFalse...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
84072
|
2899
|
1
|
2026-05-28T11:22:36.231431+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967356231_m1.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-024 github.com/jiminny/app/pull/12130/changes#diff-024e2701f53cba09fb2fd8e644d1107959e8598b1d182b1ad5876d5673e73059...
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:
Structural and Dependency Changes
Structural and Dependency Changes
Replaced Datadog:
Removed the
ChaseConey\LaravelDatadogHelper\Datadog
dependency and replaced it with
Jiminny\Component\ES\ReindexTargetStatsReporter
.
Added Constants and Properties:
Introduced a new
ENVIRONMENT
constant (set to
'testing'
) and a
$statsReporter
property to hold the mock for the new stats reporter.
Processor Instantiation:
Updated the
getProcessor()
method to inject the new
$statsReporter
mock into the
UpdateProcessManager
and utilize the
ENVIRONMENT
constant.
Test Case Modifications
Test Case Modifications
Removed Memory Logging Tests:
Deleted
testLogMemoryUsageEmitsGaugeWhenLockIsAbsent...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"AI Chat settings","depth":3,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":3,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Main menu","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open mode picker, currently 3.1 Pro","depth":6,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Gemini","depth":13,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"3.1 Pro","depth":11,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Chat","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open menu for conversation actions.","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Conversation with Gemini","depth":7,"on_screen":true,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Conversation with Gemini","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":13,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"You said","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.","depth":15,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Expand","depth":13,"on_screen":false,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Copy prompt","depth":12,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Gemini said","depth":12,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Gemini said","depth":13,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Here is a summary of the changes in the provided git diff for","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"UpdateProcessManagerTest.php","depth":17,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":":","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Structural and Dependency Changes","depth":15,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Structural and Dependency Changes","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Replaced Datadog:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Removed the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ChaseConey\\LaravelDatadogHelper\\Datadog","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"dependency and replaced it with","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Jiminny\\Component\\ES\\ReindexTargetStatsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":".","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Added Constants and Properties:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Introduced a new","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ENVIRONMENT","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"constant (set to","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"'testing'","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":") and a","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"$statsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"property to hold the mock for the new stats reporter.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Processor Instantiation:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Updated the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"getProcessor()","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"method to inject the new","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"$statsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"mock into the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"UpdateProcessManager","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"and utilize the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ENVIRONMENT","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"constant.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Test Case Modifications","depth":15,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Test Case Modifications","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Removed Memory Logging Tests:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Deleted","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testLogMemoryUsageEmitsGaugeWhenLockIsAbsent","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
2539442614114928991
|
-3259026032374026108
|
idle
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:
Structural and Dependency Changes
Structural and Dependency Changes
Replaced Datadog:
Removed the
ChaseConey\LaravelDatadogHelper\Datadog
dependency and replaced it with
Jiminny\Component\ES\ReindexTargetStatsReporter
.
Added Constants and Properties:
Introduced a new
ENVIRONMENT
constant (set to
'testing'
) and a
$statsReporter
property to hold the mock for the new stats reporter.
Processor Instantiation:
Updated the
getProcessor()
method to inject the new
$statsReporter
mock into the
UpdateProcessManager
and utilize the
ENVIRONMENT
constant.
Test Case Modifications
Test Case Modifications
Removed Memory Logging Tests:
Deleted
testLogMemoryUsageEmitsGaugeWhenLockIsAbsent...
|
84070
|
NULL
|
NULL
|
NULL
|
|
84071
|
2900
|
5
|
2026-05-28T11:22:24.848614+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967344848_m2.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-024 github.com/jiminny/app/pull/12130/changes#diff-024e2701f53cba09fb2fd8e644d1107959e8598b1d182b1ad5876d5673e73059...
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:
Structural and Dependency Changes
Structural and Dependency Changes
Replaced Datadog:
Removed the
ChaseConey\LaravelDatadogHelper\Datadog
dependency and replaced it with
Jiminny\Component\ES\ReindexTargetStatsReporter
.
Added Constants and Properties:
Introduced a new
ENVIRONMENT
constant (set to
'testing'
) and a
$statsReporter
property to hold the mock for the new stats reporter.
Processor Instantiation:
Updated the
getProcessor()
method to inject the new
$statsReporter
mock into the
UpdateProcessManager
and utilize the
ENVIRONMENT
constant.
Test Case Modifications
Test Case Modifications
Removed Memory Logging Tests:
Deleted
testLogMemoryUsageEmitsGaugeWhenLockIsAbsent
and
testLogMemoryUsageSkipsGaugeWhenLockIsPresent
entirely, as the Redis lock and Datadog gauge logic were removed.
Added Empty Selection Test:
Introduced
testEmptySelectionLogsAndReturnsFalse
to verify that processing an empty selection logs a debug message, skips batch manager operations (
generateName
,
scheduleWork
,
finishWork
), skips the stats reporter, and cleanly returns
false
.
Updated Existing Tests:
Modified
testRunUpdate
and
testRunDoUpdateButThrottled
to assert that the
$statsReporter->report()
method is called and to utilize the updated status manager mock.
Helper Method Refactoring
Helper Method Refactoring
Dynamic Status Manager Assertions:
Updated the
prepareStatusManager(int $invokeTimes = 0)
method to accept an integer. This allows tests to dynamically assert exactly how many times methods like
generateName
,
setUpdateTarget
,
scheduleWork
, and
finishWork
are invoked.
Removed Obsolete Helpers:
Deleted the
prepareLogger()
and
silenceDatadogAndRedisLock()
helper methods, replacing their inline functionality with standard
Log::shouldReceive
expectations where needed.
Good response
Bad response
Share & export
Copy
Show more options...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.11402926,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.27055067,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.28172386,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.37988827,"width":0.09740692,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"bounds":{"left":0.0,"top":0.40143654,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.41260973,"width":0.08543883,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.43415803,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.44533122,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0,"top":0.4668795,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.47805268,"width":0.10106383,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"bounds":{"left":0.0028257978,"top":0.5047885,"width":0.036070477,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0028257978,"top":0.528332,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015957447,"top":0.5395052,"width":0.013297873,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.0028257978,"top":0.56105345,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"bounds":{"left":0.015957447,"top":0.57222664,"width":0.1271609,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.5937749,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.6049481,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.62649643,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.63766956,"width":0.12134308,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.6592179,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.6703911,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.69193935,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.70311254,"width":0.18201463,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.06732048,"top":0.69912213,"width":0.007978723,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.0028257978,"top":0.72625697,"width":0.07413564,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"bounds":{"left":0.0028257978,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"bounds":{"left":0.013796543,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"bounds":{"left":0.024933511,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"bounds":{"left":0.036070477,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"bounds":{"left":0.04720745,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"AI Chat settings","depth":3,"bounds":{"left":0.35854387,"top":0.055067837,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":3,"bounds":{"left":0.37051198,"top":0.055067837,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Main menu","depth":5,"bounds":{"left":0.08228058,"top":0.09736632,"width":0.015957447,"height":0.03830806},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open mode picker, currently 3.1 Pro","depth":6,"bounds":{"left":0.09823803,"top":0.10694334,"width":0.047539894,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Gemini","depth":13,"bounds":{"left":0.1022274,"top":0.10853951,"width":0.017121011,"height":0.016360734},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"3.1 Pro","depth":11,"bounds":{"left":0.12084442,"top":0.10853951,"width":0.013796543,"height":0.015961692},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Chat","depth":5,"bounds":{"left":0.35854387,"top":0.10215483,"width":0.011968086,"height":0.028731046},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open menu for conversation actions.","depth":5,"bounds":{"left":0.37051198,"top":0.10215483,"width":0.011968086,"height":0.028731046},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Conversation with Gemini","depth":7,"bounds":{"left":0.079288565,"top":0.14445332,"width":0.0003324468,"height":0.0007980846},"on_screen":true,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Conversation with Gemini","depth":8,"bounds":{"left":0.079288565,"top":0.14684756,"width":0.1200133,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":13,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"You said","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.","depth":15,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Expand","depth":13,"on_screen":false,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Copy prompt","depth":12,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Gemini said","depth":12,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Gemini said","depth":13,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Here is a summary of the changes in the provided git diff for","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"UpdateProcessManagerTest.php","depth":17,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":":","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Structural and Dependency Changes","depth":15,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Structural and Dependency Changes","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Replaced Datadog:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Removed the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ChaseConey\\LaravelDatadogHelper\\Datadog","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"dependency and replaced it with","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Jiminny\\Component\\ES\\ReindexTargetStatsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":".","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Added Constants and Properties:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Introduced a new","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ENVIRONMENT","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"constant (set to","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"'testing'","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":") and a","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"$statsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"property to hold the mock for the new stats reporter.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Processor Instantiation:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Updated the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"getProcessor()","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"method to inject the new","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"$statsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"mock into the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"UpdateProcessManager","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"and utilize the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ENVIRONMENT","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"constant.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Test Case Modifications","depth":15,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Test Case Modifications","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Removed Memory Logging Tests:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Deleted","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testLogMemoryUsageEmitsGaugeWhenLockIsAbsent","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"and","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testLogMemoryUsageSkipsGaugeWhenLockIsPresent","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"entirely, as the Redis lock and Datadog gauge logic were removed.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Added Empty Selection Test:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Introduced","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testEmptySelectionLogsAndReturnsFalse","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"to verify that processing an empty selection logs a debug message, skips batch manager operations (","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"generateName","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":",","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"scheduleWork","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":",","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"finishWork","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"), skips the stats reporter, and cleanly returns","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"false","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":".","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Updated Existing Tests:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Modified","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testRunUpdate","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"and","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testRunDoUpdateButThrottled","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"to assert that the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"$statsReporter->report()","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"method is called and to utilize the updated status manager mock.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Helper Method Refactoring","depth":15,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Helper Method Refactoring","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Dynamic Status Manager Assertions:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Updated the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"prepareStatusManager(int $invokeTimes = 0)","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"method to accept an integer. This allows tests to dynamically assert exactly how many times methods like","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"generateName","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":",","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"setUpdateTarget","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":",","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"scheduleWork","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":", and","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"finishWork","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"are invoked.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Removed Obsolete Helpers:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Deleted the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"prepareLogger()","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"and","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"silenceDatadogAndRedisLock()","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"helper methods, replacing their inline functionality with standard","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Log::shouldReceive","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"expectations where needed.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXCheckBox","text":"Good response","depth":15,"on_screen":false,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Bad response","depth":15,"on_screen":false,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Share & export","depth":14,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Copy","depth":15,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Show more options","depth":14,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
-201985485679767272
|
-3403141220450930556
|
idle
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:
Structural and Dependency Changes
Structural and Dependency Changes
Replaced Datadog:
Removed the
ChaseConey\LaravelDatadogHelper\Datadog
dependency and replaced it with
Jiminny\Component\ES\ReindexTargetStatsReporter
.
Added Constants and Properties:
Introduced a new
ENVIRONMENT
constant (set to
'testing'
) and a
$statsReporter
property to hold the mock for the new stats reporter.
Processor Instantiation:
Updated the
getProcessor()
method to inject the new
$statsReporter
mock into the
UpdateProcessManager
and utilize the
ENVIRONMENT
constant.
Test Case Modifications
Test Case Modifications
Removed Memory Logging Tests:
Deleted
testLogMemoryUsageEmitsGaugeWhenLockIsAbsent
and
testLogMemoryUsageSkipsGaugeWhenLockIsPresent
entirely, as the Redis lock and Datadog gauge logic were removed.
Added Empty Selection Test:
Introduced
testEmptySelectionLogsAndReturnsFalse
to verify that processing an empty selection logs a debug message, skips batch manager operations (
generateName
,
scheduleWork
,
finishWork
), skips the stats reporter, and cleanly returns
false
.
Updated Existing Tests:
Modified
testRunUpdate
and
testRunDoUpdateButThrottled
to assert that the
$statsReporter->report()
method is called and to utilize the updated status manager mock.
Helper Method Refactoring
Helper Method Refactoring
Dynamic Status Manager Assertions:
Updated the
prepareStatusManager(int $invokeTimes = 0)
method to accept an integer. This allows tests to dynamically assert exactly how many times methods like
generateName
,
setUpdateTarget
,
scheduleWork
, and
finishWork
are invoked.
Removed Obsolete Helpers:
Deleted the
prepareLogger()
and
silenceDatadogAndRedisLock()
helper methods, replacing their inline functionality with standard
Log::shouldReceive
expectations where needed.
Good response
Bad response
Share & export
Copy
Show more options...
|
84069
|
NULL
|
NULL
|
NULL
|
|
84070
|
2899
|
0
|
2026-05-28T11:22:06.031671+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967326031_m1.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-024 github.com/jiminny/app/pull/12130/changes#diff-024e2701f53cba09fb2fd8e644d1107959e8598b1d182b1ad5876d5673e73059...
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
-8478200795328864393
|
-3106541392062253853
|
click
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
84069
|
2900
|
4
|
2026-05-28T11:21:54.511410+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967314511_m2.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-024 github.com/jiminny/app/pull/12130/changes#diff-024e2701f53cba09fb2fd8e644d1107959e8598b1d182b1ad5876d5673e73059...
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:
Structural and Dependency Changes
Structural and Dependency Changes
Replaced Datadog:
Removed the
ChaseConey\LaravelDatadogHelper\Datadog
dependency and replaced it with
Jiminny\Component\ES\ReindexTargetStatsReporter
.
Added Constants and Properties:
Introduced a new
ENVIRONMENT
constant (set to
'testing'
) and a
$statsReporter
property to hold the mock for the new stats reporter.
Processor Instantiation:
Updated the
getProcessor()
method to inject the new
$statsReporter
mock into the
UpdateProcessManager
and utilize the
ENVIRONMENT
constant.
Test Case Modifications
Test Case Modifications
Removed Memory Logging Tests:
Deleted
testLogMemoryUsageEmitsGaugeWhenLockIsAbsent
and
testLogMemoryUsageSkipsGaugeWhenLockIsPresent
entirely, as the Redis lock and Datadog gauge logic were removed.
Added Empty Selection Test:
Introduced
testEmptySelectionLogsAndReturnsFalse
to verify that processing an empty selection logs a debug message, skips batch manager operations (
generateName
,
scheduleWork
,
finishWork
), skips the stats reporter, and cleanly returns
false
.
Updated Existing Tests:
Modified
testRunUpdate
and
testRunDoUpdateButThrottled
to assert that the
$statsReporter->report()
method is called and to utilize the updated status manager mock.
Helper Method Refactoring
Helper Method Refactoring
Dynamic Status Manager Assertions:
Updated the
prepareStatusManager(int $invokeTimes = 0)
method to accept an integer. This allows tests to dynamically assert exactly how many times methods like
generateName
,
setUpdateTarget
,
scheduleWork
, and
finishWork
are invoked.
Removed Obsolete Helpers:
Deleted the
prepareLogger()
and
silenceDatadogAndRedisLock()
helper methods, replacing their inline functionality with standard
Log::shouldReceive
expectations where needed.
Good response
Bad response
Share & export
Copy
Show more options
You said find potential issues...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.11402926,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.27055067,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.28172386,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.37988827,"width":0.09740692,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"bounds":{"left":0.0,"top":0.40143654,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.41260973,"width":0.08543883,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.43415803,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.44533122,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0,"top":0.4668795,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.47805268,"width":0.10106383,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"bounds":{"left":0.0028257978,"top":0.5047885,"width":0.036070477,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0028257978,"top":0.528332,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015957447,"top":0.5395052,"width":0.013297873,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.0028257978,"top":0.56105345,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"bounds":{"left":0.015957447,"top":0.57222664,"width":0.1271609,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.5937749,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.6049481,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.62649643,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.63766956,"width":0.12134308,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.6592179,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.6703911,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.69193935,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.70311254,"width":0.18201463,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.06732048,"top":0.69912213,"width":0.007978723,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.0028257978,"top":0.72625697,"width":0.07413564,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"bounds":{"left":0.0028257978,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"bounds":{"left":0.013796543,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"bounds":{"left":0.024933511,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"bounds":{"left":0.036070477,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"bounds":{"left":0.04720745,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"AI Chat settings","depth":3,"bounds":{"left":0.35854387,"top":0.055067837,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":3,"bounds":{"left":0.37051198,"top":0.055067837,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Main menu","depth":5,"bounds":{"left":0.08228058,"top":0.09736632,"width":0.015957447,"height":0.03830806},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open mode picker, currently 3.1 Pro","depth":6,"bounds":{"left":0.09823803,"top":0.10694334,"width":0.047539894,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Gemini","depth":13,"bounds":{"left":0.1022274,"top":0.10853951,"width":0.017121011,"height":0.016360734},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"3.1 Pro","depth":11,"bounds":{"left":0.12084442,"top":0.10853951,"width":0.013796543,"height":0.015961692},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Chat","depth":5,"bounds":{"left":0.35854387,"top":0.10215483,"width":0.011968086,"height":0.028731046},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open menu for conversation actions.","depth":5,"bounds":{"left":0.37051198,"top":0.10215483,"width":0.011968086,"height":0.028731046},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Conversation with Gemini","depth":7,"bounds":{"left":0.079288565,"top":0.14445332,"width":0.0003324468,"height":0.0007980846},"on_screen":true,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Conversation with Gemini","depth":8,"bounds":{"left":0.079288565,"top":0.14684756,"width":0.1200133,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":13,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"You said","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.","depth":15,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Expand","depth":13,"on_screen":false,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Copy prompt","depth":12,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Gemini said","depth":12,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Gemini said","depth":13,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Here is a summary of the changes in the provided git diff for","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"UpdateProcessManagerTest.php","depth":17,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":":","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Structural and Dependency Changes","depth":15,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Structural and Dependency Changes","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Replaced Datadog:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Removed the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ChaseConey\\LaravelDatadogHelper\\Datadog","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"dependency and replaced it with","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Jiminny\\Component\\ES\\ReindexTargetStatsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":".","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Added Constants and Properties:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Introduced a new","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ENVIRONMENT","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"constant (set to","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"'testing'","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":") and a","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"$statsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"property to hold the mock for the new stats reporter.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Processor Instantiation:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Updated the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"getProcessor()","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"method to inject the new","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"$statsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"mock into the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"UpdateProcessManager","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"and utilize the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ENVIRONMENT","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"constant.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Test Case Modifications","depth":15,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Test Case Modifications","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Removed Memory Logging Tests:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Deleted","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testLogMemoryUsageEmitsGaugeWhenLockIsAbsent","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"and","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testLogMemoryUsageSkipsGaugeWhenLockIsPresent","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"entirely, as the Redis lock and Datadog gauge logic were removed.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Added Empty Selection Test:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Introduced","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testEmptySelectionLogsAndReturnsFalse","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"to verify that processing an empty selection logs a debug message, skips batch manager operations (","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"generateName","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":",","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"scheduleWork","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":",","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"finishWork","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"), skips the stats reporter, and cleanly returns","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"false","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":".","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Updated Existing Tests:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Modified","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testRunUpdate","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"and","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testRunDoUpdateButThrottled","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"to assert that the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"$statsReporter->report()","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"method is called and to utilize the updated status manager mock.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Helper Method Refactoring","depth":15,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Helper Method Refactoring","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Dynamic Status Manager Assertions:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Updated the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"prepareStatusManager(int $invokeTimes = 0)","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"method to accept an integer. This allows tests to dynamically assert exactly how many times methods like","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"generateName","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":",","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"setUpdateTarget","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":",","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"scheduleWork","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":", and","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"finishWork","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"are invoked.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Removed Obsolete Helpers:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Deleted the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"prepareLogger()","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"and","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"silenceDatadogAndRedisLock()","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"helper methods, replacing their inline functionality with standard","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Log::shouldReceive","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"expectations where needed.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXCheckBox","text":"Good response","depth":15,"on_screen":false,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Bad response","depth":15,"on_screen":false,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Share & export","depth":14,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Copy","depth":15,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Show more options","depth":14,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"You said find potential issues","depth":13,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"}]...
|
4919563129565141
|
-3114910844299218812
|
visual_change
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:
Structural and Dependency Changes
Structural and Dependency Changes
Replaced Datadog:
Removed the
ChaseConey\LaravelDatadogHelper\Datadog
dependency and replaced it with
Jiminny\Component\ES\ReindexTargetStatsReporter
.
Added Constants and Properties:
Introduced a new
ENVIRONMENT
constant (set to
'testing'
) and a
$statsReporter
property to hold the mock for the new stats reporter.
Processor Instantiation:
Updated the
getProcessor()
method to inject the new
$statsReporter
mock into the
UpdateProcessManager
and utilize the
ENVIRONMENT
constant.
Test Case Modifications
Test Case Modifications
Removed Memory Logging Tests:
Deleted
testLogMemoryUsageEmitsGaugeWhenLockIsAbsent
and
testLogMemoryUsageSkipsGaugeWhenLockIsPresent
entirely, as the Redis lock and Datadog gauge logic were removed.
Added Empty Selection Test:
Introduced
testEmptySelectionLogsAndReturnsFalse
to verify that processing an empty selection logs a debug message, skips batch manager operations (
generateName
,
scheduleWork
,
finishWork
), skips the stats reporter, and cleanly returns
false
.
Updated Existing Tests:
Modified
testRunUpdate
and
testRunDoUpdateButThrottled
to assert that the
$statsReporter->report()
method is called and to utilize the updated status manager mock.
Helper Method Refactoring
Helper Method Refactoring
Dynamic Status Manager Assertions:
Updated the
prepareStatusManager(int $invokeTimes = 0)
method to accept an integer. This allows tests to dynamically assert exactly how many times methods like
generateName
,
setUpdateTarget
,
scheduleWork
, and
finishWork
are invoked.
Removed Obsolete Helpers:
Deleted the
prepareLogger()
and
silenceDatadogAndRedisLock()
helper methods, replacing their inline functionality with standard
Log::shouldReceive
expectations where needed.
Good response
Bad response
Share & export
Copy
Show more options
You said find potential issues...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
84068
|
2900
|
3
|
2026-05-28T11:21:50.974243+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967310974_m2.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-024 github.com/jiminny/app/pull/12130/changes#diff-024e2701f53cba09fb2fd8e644d1107959e8598b1d182b1ad5876d5673e73059...
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.11402926,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.27055067,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.28172386,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
4076172443549847402
|
-5709619777657511209
|
click
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app...
|
84067
|
NULL
|
NULL
|
NULL
|
|
84067
|
2900
|
2
|
2026-05-28T11:21:49.477765+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967309477_m2.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-024 github.com/jiminny/app/pull/12130/changes#diff-024e2701f53cba09fb2fd8e644d1107959e8598b1d182b1ad5876d5673e73059...
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
rircroxViewhistonooountrnPotLe.lootWindow=github.c rircroxViewhistonooountrnPotLe.lootWindow=github.comnel:v Gooc e GeminiPipelines - jiminny/appGemini 3.1 Pro ~reavors now ownerstoe tooapp/component/es/entitylypeReindexer.php+soLines changea: so additions & U deletionsAxUemered tines on New codJY-20963 fix deleted object impOriginal tile line numoer Oniginal tile linebim line numbereyJiminny\Exceptions(EmailActivityfrM Inbox (1,733) - luicas.kovaliklimirioonre Reso ve php 81.15 dedThis is a solid refactor. Moving towards a supervisor-worker model using pentl_fork and cleaniup the araceful shutdown traits are great steps for reliability.Here is a detailed review of the PR, focusing on architectural risks, concurrency issues, and potennwlenecksPlatform Sorint 5.02 - Platform Te8 JiminnySona Strbramaal an at 27/05/2021aIliyana Netseva at 27/05/2026, 1€) Jy 20910 schedule parallel upc X* Critical Architectural Risks1. Unpurged Elasticsearch Connections After ForkLocation: app//Console/Commands/Elasticsearch/AsyncUpdateSupervisor.php Lines-147-159 in resetAfterForko )Issue: You correctly recognized that TCP sockets must be purged after pcntl_fork() andimolemented connection resets for MySOL( DB: :reconnecto) and RedisPeris. nurde ol Howover. Easticcenrch connec tions are not ourdeo)Impact: Most Elasticsearch SDKs (includina Guzzle under the hood) use connection poolingpersistent sockets. If the parent orocess opens an HiniP socket to ES before forkina, ali childprocesses will inherit that exact same file descriptor. This will lead to interleaved HTTP requecoruoeo oara oodies, and troken oide orcuktexceodonsFix: Ensure that your ElasticSearchelient is completely reinstantiated or its underlyingGuzzle handler/curi sockets are closed inside resetAfterForko .2. Supervisor Deadlock During Child ReapinalLocation: app/Console/Commands/Elasticsearch/AsyncUpdateSupervisor.php (Linesachitdran!elcomintYor lim now Chate tiho" uend to imntouy our moddle Camioie Allt Cao mats mttakse co donbls chach" Yoir ornacysôtSummarize page...
|
NULL
|
4854384090392818794
|
NULL
|
click
|
ocr
|
NULL
|
rircroxViewhistonooountrnPotLe.lootWindow=github.c rircroxViewhistonooountrnPotLe.lootWindow=github.comnel:v Gooc e GeminiPipelines - jiminny/appGemini 3.1 Pro ~reavors now ownerstoe tooapp/component/es/entitylypeReindexer.php+soLines changea: so additions & U deletionsAxUemered tines on New codJY-20963 fix deleted object impOriginal tile line numoer Oniginal tile linebim line numbereyJiminny\Exceptions(EmailActivityfrM Inbox (1,733) - luicas.kovaliklimirioonre Reso ve php 81.15 dedThis is a solid refactor. Moving towards a supervisor-worker model using pentl_fork and cleaniup the araceful shutdown traits are great steps for reliability.Here is a detailed review of the PR, focusing on architectural risks, concurrency issues, and potennwlenecksPlatform Sorint 5.02 - Platform Te8 JiminnySona Strbramaal an at 27/05/2021aIliyana Netseva at 27/05/2026, 1€) Jy 20910 schedule parallel upc X* Critical Architectural Risks1. Unpurged Elasticsearch Connections After ForkLocation: app//Console/Commands/Elasticsearch/AsyncUpdateSupervisor.php Lines-147-159 in resetAfterForko )Issue: You correctly recognized that TCP sockets must be purged after pcntl_fork() andimolemented connection resets for MySOL( DB: :reconnecto) and RedisPeris. nurde ol Howover. Easticcenrch connec tions are not ourdeo)Impact: Most Elasticsearch SDKs (includina Guzzle under the hood) use connection poolingpersistent sockets. If the parent orocess opens an HiniP socket to ES before forkina, ali childprocesses will inherit that exact same file descriptor. This will lead to interleaved HTTP requecoruoeo oara oodies, and troken oide orcuktexceodonsFix: Ensure that your ElasticSearchelient is completely reinstantiated or its underlyingGuzzle handler/curi sockets are closed inside resetAfterForko .2. Supervisor Deadlock During Child ReapinalLocation: app/Console/Commands/Elasticsearch/AsyncUpdateSupervisor.php (Linesachitdran!elcomintYor lim now Chate tiho" uend to imntouy our moddle Camioie Allt Cao mats mttakse co donbls chach" Yoir ornacysôtSummarize page...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
84059
|
2898
|
47
|
2026-05-28T11:21:23.340949+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967283340_m2.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-024 github.com/jiminny/app/pull/12130/changes#diff-024e2701f53cba09fb2fd8e644d1107959e8598b1d182b1ad5876d5673e73059...
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
-8578556159445200548
|
4739486653691733234
|
visual_change
|
hybrid
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
rircroxViewhsttonooountrnroie.WindowHelp• =github.com/~ Google GeminiGemini 3.1 Pro ~100% KSa: 8- Thu 28 May 14:21:23e644d1107959e8598b1d182b1ad5876d5673e73059Pipelines - jiminny/app(JY-20613) Allow owner's role to bxUewredtines on New codJY-20963 fix deleted object impsm.cwdSycaotionslsmalldcthatteM Inbox (1,733) - lukas.kovalik@jiminioonre Reso ve php 81.15 dedPlatform Sorint 5.02 - Platform Te8 JiminnySona Strbramaal an at 27/05/2021O Illyana Netsova at 27/05/2026, 18Jy 20910 schedule parallel upc Xapp/Component/ES/EntityTypeReindexer.php+soLines changea: so additions & U deletionsOriginal tile line numoer Oniginal tile linebim line numbereyThis is a solid refactor. Moving towards a supervisor-worker model using pentl_fork and cleaningup the graceful shutdown traits are great steps for reliability.Here is a detailed review of the PR, focusing on architectural risks, concurrency issues, and potentialbottlenecks.8 Critical Architectural Risks1. Unpurged Elasticsearch Connections After ForkLocation: app/Console/Comnands/Elasticsearch/AsyncUpdateSupervisor.php (Lines-147-159 in resetAfterFork() )Issue: You correctly recognized that TCP sockets must be purged after pentl_fork() andimplemented connection resets for MySQL ( DB: :reconnect()) ) and RedisPeris. nurde ol Howover. Easticcenrch connec tions are not ourdeo)Impact: Most Elasticsearch SDKs (including Guzzle under the hood) use connection pooling/persistent sockets. If the parent process opens an HTTP socket to ES before forking, all childprocesses will inherit that exact same file descriptor. This will lead to interleaved HTTP requests,coruoeo oara oodies, and troken oide orcuktexceodonsFix: Ensure that your ElasticSearchelient is completely reinstantiated or its underlyingGuzzle handler/curl sockets are closed inside resetAfterFork().2. Supervisor Deadlock During Child ReapingLocation: app/Console/Commands/Elasticsearch/AsyncUpdateSupervisor.php (Linesachitdran!Ask GeminiYor lim now chate thn" uend to imntoy our modale Camioie Alit cao mata mttrkae co donbld chachit Yoir mracy & CaminiSummarize pageI OpenJy 20910 schedule parallel uodate target processing 81230All commits - | Vasil-Jiminny wants to merge 65 commits into naster from JY-20918-schedule-parallel-update-target-processing d• Filter hiles.v apo/Console/Coenands/Elasticsearch/AsvncUodateSupervisor.oho /ee -0,0 +1,283 ge~ Б app~ Ei Component/ESEntityTypeReindexer.phpE ReindexTargetStatsReporter,p...UpdateProcessManager.php~ # Console |v E Commande/FlastincearchAsyncUpdateEsEntities.phpAsyncUpdateSupervisor.php- DeleteEmailDocumentsCom…ReindexEntityTypes.php•1 RemoveGhostParticipantsCo.….8 ResetAsyncElasticSearchCo.* Kernel. php~ # Contracts/ESD StopSignallinterface.php~ Ei TraitsP GracefullvStonoable.ohov # tests/Unit/Component/ESEntityTypeReindexerTest.phpReindexTargetStatsReporterTes.UpdateProcessManagerTest.php© 2 /15 viewedAnaiunt approv4203 BBBBn Viewed-C ont+ declare(stricttypes=)):I+ nanespace Jininny console commands \clas cicsearch:+ use Illuminate\Console\Conmand;+ use Illuminate\Support\Facades\Cont1g:+ use IlluminatelSupport\Facades\DB:* use Illuminate\Support\Facades\Log;|+ use Illuminate\Support\Facades\Redis:+ use iminny Conoonent\ES Processorl Uodaterarcet:* use Jiminny Exceptions\RuntimeException:• useseinay Tratte Gracetullystoonable+ * A Supervisor class that will spawn child processes - each dedicated at processing aloarticularl18 + [* group of entity types. The class gracefully handles child process termination andnestarts19 + *+ class AsyncUodateSuoeryisor extends Commancuse GracetullvStoopableGracefullyStoppabler:shutdown as signalHandlerShutdown;orivate const int MONITOR POLL SECONOS = S* The paraneter "runforSeconds" is unused, but rensins purely to guarantee*any calis tron the actual suceryisord with a oarareter cunolted will not trieoer* "an unknown option" error.protected Ssignature = 'es:update-entities (--runForSeconds»SS : Seconds to run thecommand"Tee evar arravestring. Ints SchildPids Mao of taroet o child PID ehnetunte areas tohiiaoide enuhlie tunetion chutdount). vniatos..tofolitG/eueelledat/Ghreitae Chutdae einanl meatuadetansinot...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
84054
|
2898
|
44
|
2026-05-28T11:20:58.720205+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967258720_m2.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Fircrox© Pipelines - |Iminnylapp(JY-20613) Allow o Fircrox© Pipelines - |Iminnylapp(JY-20613) Allow owner's role to bxUewredtines on New codJY-20963 fix deleted object impsJiminny\Exceptions(EmailActivityfrM Inbox (1,733) - lukas.kovalik@jiminioonre Reso ve php 81.15 dedPlatform Sorint 5.02 - Platform Te8 JiminnySona Subramaaian at 27/05/202O Illyana Netsova at 27/05/2026, 18Jy 20910 schedule parallel up: X=github.con~ Google GeminiGemini 3.1 Pro ~app/Component/ES/EntityTypeReindexer.php+soLines changea: so additions & U deletionsOriginal tile line numoer Oniginal tile linebim line numbereyThis is a solid refactor. Moving towards a supervisor-worker model using pentl_fork and cleaningup the graceful shutdown traits are great steps for reliability.Here is a detailed review of the PR, focusing on architectural risks, concurrency issues, and potentialmtlenocks8 Critical Architectural Risks1. Unpurged Elasticsearch Connections After ForkLocation: app/Console/Commands/Elasticsearch/AsyncUpdateSupervisor.php (Lines-147-159 in resetAfterFork() )Issue: You correctly recognized that TCP sockets must be purged after pentl_fork() andimplemented connection resets for MySQL ( DB: :reconnect()) ) and RedisPeris. nurde ol However. E asticcenrch connec tons are not ourdeo)Impact: Most Elasticsearch SDKs (including Guzzle under the hood) use connection pooling/persistent sockets. If the parent process opens an HTTP socket to ES before forking, all childprocesses will inherit that exact same file descriptor. This will lead to interleaved HTTP requests,coruoeo cara oodies, and troken oide orcuktexceodonsFix: Ensure that your ElasticSearchelient is completely reinstantiated or its underiyingGuzzle handler/curl sockets are closed inside resetAfterFork().2. Supervisor Deadlock During Child ReapingLocation: app/Console/Commands/Elasticsearch/AsyncUpdateSupervisor.php (Linesachitdran!Ask GeminiYour Jiminny chats aren't used to improve our modeis. Gemini is Al. It can make mistakes, so double check it. Your privacy & GeminSummarize pageI1 OpenJy 20910 schedule parallel uodate tarcet processing 8121130All commits - | Vasil-Jiminny wants to merge 65 commits into naster from JY-20910-schedule-parallel-update-target-processingCFilter tes.app/Traits/GracefullyStoppable.php C ÷~ # app~ fi Component/ESEntityTypeReindexer.phpE ReindexTargetStatsReporter,p...UpdateProcessManager.php~ Si Console~ #i Commands/ElasticsearchAsyncUpdateEsEntities.phpD AsyncUpdateSupervisor.phpDeleteEmailDocumentsCom…ReindexEntityTypes.php•1 RemoveGhostParticipantsCo.….128if (Sthis instanceof Command) &Sthis-yarn(ssessaoe)122J else &logger-warning(Snessaoc)124v tests/Unit/Component/ES/EntityTypeReindexerTest.php C.*• @e -0,0 +1,124 ge8 ResetAsyncElasticSearchCo..Kernel.php~ # Contracts/ESD StopSignallinterface.php~ Ei TraitsB GracefullyStoppable.php~ E tests/Unit/Component/ESEntityTypeReindexerTest.phpReindexTargetStatsReporterTes…UpdateProcessManagerTest.php124•SOMO0100% K53 8 • Thu 28 May 14:20:580 2/15 viewedAnaiunt approva$44 -43 BB00 M Viewedif (Sthis instanceof Comnand) &sthis-swarnmessage)+124 BBBBD Viewed .A ь WWOEESNHONEEESBS+ €7ohd+ declare(strict_types=1):+ nasesoace Tes sUnte cocoonentt%+ use Jiminny Component ES EntitytvoeReindexer:+ use Jiminny\Component\ES\UpdateProcessManager;+ use Jiminny contracts es Stopsignalintertacer* use PHPUnit\Franework\Attributes\CoversClass;use YhYunrrobework mockoolect hocxboler+ use PHPUnit\Franework\TestCase:+ e[CoversClass (EntityTypeReindexer::class)]+ class EntityTypeReindexerTest extends TestCaseprivate const int USLEEP = 1_000;private const string TARGET = 'activities';private const string ENVIRONMENT = 'testing";private UpdateProcessManager |MockObject SupdateProcessManager:protected function setupt): voidparent::setUp(:Sthis->updateProcessManager = Sthis->createMock(UpdateProcessManager::class) =public function testRunConfiguresManagerAndExecutes0neChunkThenStops(): voidSthise-uodateProcessManacer-sexoectslsthiceboncet)>nethod ("setEnvironsent")...
|
NULL
|
7077010602657580112
|
NULL
|
click
|
ocr
|
NULL
|
Fircrox© Pipelines - |Iminnylapp(JY-20613) Allow o Fircrox© Pipelines - |Iminnylapp(JY-20613) Allow owner's role to bxUewredtines on New codJY-20963 fix deleted object impsJiminny\Exceptions(EmailActivityfrM Inbox (1,733) - lukas.kovalik@jiminioonre Reso ve php 81.15 dedPlatform Sorint 5.02 - Platform Te8 JiminnySona Subramaaian at 27/05/202O Illyana Netsova at 27/05/2026, 18Jy 20910 schedule parallel up: X=github.con~ Google GeminiGemini 3.1 Pro ~app/Component/ES/EntityTypeReindexer.php+soLines changea: so additions & U deletionsOriginal tile line numoer Oniginal tile linebim line numbereyThis is a solid refactor. Moving towards a supervisor-worker model using pentl_fork and cleaningup the graceful shutdown traits are great steps for reliability.Here is a detailed review of the PR, focusing on architectural risks, concurrency issues, and potentialmtlenocks8 Critical Architectural Risks1. Unpurged Elasticsearch Connections After ForkLocation: app/Console/Commands/Elasticsearch/AsyncUpdateSupervisor.php (Lines-147-159 in resetAfterFork() )Issue: You correctly recognized that TCP sockets must be purged after pentl_fork() andimplemented connection resets for MySQL ( DB: :reconnect()) ) and RedisPeris. nurde ol However. E asticcenrch connec tons are not ourdeo)Impact: Most Elasticsearch SDKs (including Guzzle under the hood) use connection pooling/persistent sockets. If the parent process opens an HTTP socket to ES before forking, all childprocesses will inherit that exact same file descriptor. This will lead to interleaved HTTP requests,coruoeo cara oodies, and troken oide orcuktexceodonsFix: Ensure that your ElasticSearchelient is completely reinstantiated or its underiyingGuzzle handler/curl sockets are closed inside resetAfterFork().2. Supervisor Deadlock During Child ReapingLocation: app/Console/Commands/Elasticsearch/AsyncUpdateSupervisor.php (Linesachitdran!Ask GeminiYour Jiminny chats aren't used to improve our modeis. Gemini is Al. It can make mistakes, so double check it. Your privacy & GeminSummarize pageI1 OpenJy 20910 schedule parallel uodate tarcet processing 8121130All commits - | Vasil-Jiminny wants to merge 65 commits into naster from JY-20910-schedule-parallel-update-target-processingCFilter tes.app/Traits/GracefullyStoppable.php C ÷~ # app~ fi Component/ESEntityTypeReindexer.phpE ReindexTargetStatsReporter,p...UpdateProcessManager.php~ Si Console~ #i Commands/ElasticsearchAsyncUpdateEsEntities.phpD AsyncUpdateSupervisor.phpDeleteEmailDocumentsCom…ReindexEntityTypes.php•1 RemoveGhostParticipantsCo.….128if (Sthis instanceof Command) &Sthis-yarn(ssessaoe)122J else &logger-warning(Snessaoc)124v tests/Unit/Component/ES/EntityTypeReindexerTest.php C.*• @e -0,0 +1,124 ge8 ResetAsyncElasticSearchCo..Kernel.php~ # Contracts/ESD StopSignallinterface.php~ Ei TraitsB GracefullyStoppable.php~ E tests/Unit/Component/ESEntityTypeReindexerTest.phpReindexTargetStatsReporterTes…UpdateProcessManagerTest.php124•SOMO0100% K53 8 • Thu 28 May 14:20:580 2/15 viewedAnaiunt approva$44 -43 BB00 M Viewedif (Sthis instanceof Comnand) &sthis-swarnmessage)+124 BBBBD Viewed .A ь WWOEESNHONEEESBS+ €7ohd+ declare(strict_types=1):+ nasesoace Tes sUnte cocoonentt%+ use Jiminny Component ES EntitytvoeReindexer:+ use Jiminny\Component\ES\UpdateProcessManager;+ use Jiminny contracts es Stopsignalintertacer* use PHPUnit\Franework\Attributes\CoversClass;use YhYunrrobework mockoolect hocxboler+ use PHPUnit\Franework\TestCase:+ e[CoversClass (EntityTypeReindexer::class)]+ class EntityTypeReindexerTest extends TestCaseprivate const int USLEEP = 1_000;private const string TARGET = 'activities';private const string ENVIRONMENT = 'testing";private UpdateProcessManager |MockObject SupdateProcessManager:protected function setupt): voidparent::setUp(:Sthis->updateProcessManager = Sthis->createMock(UpdateProcessManager::class) =public function testRunConfiguresManagerAndExecutes0neChunkThenStops(): voidSthise-uodateProcessManacer-sexoectslsthiceboncet)>nethod ("setEnvironsent")...
|
84052
|
NULL
|
NULL
|
NULL
|
|
84053
|
2897
|
33
|
2026-05-28T11:20:58.946486+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967258946_m1.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
•JAlActivity MonitorFileEditViewWindowHelpActivity •JAlActivity MonitorFileEditViewWindowHelpActivity MonitorAll ProcessesProcess Name% CPUkernel_taskPhpStormWindowServerVirtual Machine Service for DockerFirefoxCP Isolated Web ContentreplaydFirefox GPU Helpercef_server Helper (GPU)Firefoxmds_storescef_serverSlack HelperscreenpipeFirefoxCP Isolated Web ContentActivity MonitorSlack Helper (Renderer)logdcoreaudiodlanguage_server_macos_armcef_server Helper (Renderer)DockerWispr Flow Helper (Renderer)FirefoxCP Isolated Web ContentWispr FlowiTerm2ClaudebluetoothdKarabiner-Core-Service201,0108,994,476,935,333,130,320,017,316,312,312,211,99,89,46,56,45,33,93,63,53,22,92,82,51,71,71,7CPU Time19:05:57,277:35:49,716:39:07,1043:42,491:10,804:09:58,892:11:05,815:21,521:32:25,5657:12,833:47,529:35,002:53:23,3819:42,327,5645:19,0912:34,4147:25,6934:01,655:34,141:30,4833,3311:36,0625,4657:09,0825:27,3716:31,3417:44,61System:User:Idle:Threads % ['8• Thu 28 May 14:20:58CPUMemoryEnergyDiskNetworkIdle Wake-UpsKind % GPUAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleApple53,09%46,56%0,35%CPU LOAD0,021,263,30,00,00,04,64,60,00,00,03,20,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,0Threads:Processes:GPU Time0,0010:04,962:30:39,390,000,000,0022:45,051:16,320,040,000,004:26,604:47,530,000,000,000,000,000,000,000,000,000,000,0016,460,000,000,00PID alalUserrootlukaswindowserverlukaslukaslukaslukaslukaslukasrootlukaslukaslukaslukaslukaslukasroot_coreaudiodlukaslukaslukaslukaslukaslukaslukaslukasrootrootSearch...
|
NULL
|
7699424969741177769
|
NULL
|
click
|
ocr
|
NULL
|
•JAlActivity MonitorFileEditViewWindowHelpActivity •JAlActivity MonitorFileEditViewWindowHelpActivity MonitorAll ProcessesProcess Name% CPUkernel_taskPhpStormWindowServerVirtual Machine Service for DockerFirefoxCP Isolated Web ContentreplaydFirefox GPU Helpercef_server Helper (GPU)Firefoxmds_storescef_serverSlack HelperscreenpipeFirefoxCP Isolated Web ContentActivity MonitorSlack Helper (Renderer)logdcoreaudiodlanguage_server_macos_armcef_server Helper (Renderer)DockerWispr Flow Helper (Renderer)FirefoxCP Isolated Web ContentWispr FlowiTerm2ClaudebluetoothdKarabiner-Core-Service201,0108,994,476,935,333,130,320,017,316,312,312,211,99,89,46,56,45,33,93,63,53,22,92,82,51,71,71,7CPU Time19:05:57,277:35:49,716:39:07,1043:42,491:10,804:09:58,892:11:05,815:21,521:32:25,5657:12,833:47,529:35,002:53:23,3819:42,327,5645:19,0912:34,4147:25,6934:01,655:34,141:30,4833,3311:36,0625,4657:09,0825:27,3716:31,3417:44,61System:User:Idle:Threads % ['8• Thu 28 May 14:20:58CPUMemoryEnergyDiskNetworkIdle Wake-UpsKind % GPUAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleAppleApple53,09%46,56%0,35%CPU LOAD0,021,263,30,00,00,04,64,60,00,00,03,20,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,0Threads:Processes:GPU Time0,0010:04,962:30:39,390,000,000,0022:45,051:16,320,040,000,004:26,604:47,530,000,000,000,000,000,000,000,000,000,000,0016,460,000,000,00PID alalUserrootlukaswindowserverlukaslukaslukaslukaslukaslukasrootlukaslukaslukaslukaslukaslukasroot_coreaudiodlukaslukaslukaslukaslukaslukaslukaslukasrootrootSearch...
|
84051
|
NULL
|
NULL
|
NULL
|
|
84047
|
2898
|
41
|
2026-05-28T11:19:23.320432+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967163320_m2.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
2578534083018759891
|
-2178800898474990384
|
visual_change
|
hybrid
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
FirefoxPipelines - jiminny/appBE uporade libraries* (JY-20613) Allow owner's role to tText relayDeleted object error6s Uncovered Lines on New CodeJY-20963 fix deleted object impsoain alestorchJiminny\Exceptions(EmailActivityfrM Inbox (1,733) - lukas.kovalik@jiminioonre Reso ve php 81.15 ded8 Jiminm,Platform Sorint 5.02 - Platform Te8 Jiminny* (SRD-6881) (0n demand) TranscSona Strbramaal an at 27/05/2021O Illyana Netsova at 27/05/2026, 18aJimin.Jy 20910 schedule parallel upe— Now TabViewHistoryooonnsinePotLe.WindowHelp= github.com/~ Google GeminiGemini 3.1 Pro ~REview PR, be very detailed and tyr to find potential issuesand oor enecks.ntount retum the ocationtle and line)PSAsk GeminilYor lim nou chate teho' uend to imnrmy our moddle Camialie 411t can mata mttnkae co donbls chact" Yoir orhacy & CaminSummarize pageI1 OpenJy 20910 schedule parallel uodate target processing 812 130| Vasil-Jiminny wants to merge 65 commits into naster from JY-20910-schedule-parallel-update-target-processingapp/Traits/GracefullyStoppable.phpQ Filter files...~ & app~ fi Component/ESEntityTypeReindexer.phpReindexTargetStatsReporter,p...UpdateProcessManager.phpConsolefi Commands/ElasticsearchAsyncUpdateEsEntities.phpAsyncUpdateSupervisor.phpDeleteEmailDocumentsCom…ReindexEntityIypes.phpdie();public function pausel: voidstns-oshalPauseSthis->shallPause = true;sthrseornurcssoocusprintftHostnase "s pid is paused.gethostnane(),$IP GracefullvStonoable.oho~ Ei tests/Unit/Component/ESEntityTypeReindexerTest.phpReindexTargetStatsReporterTes…® UpdateProcessManagerTest.phpsprintf(hostnaesoots resuucoegethostnane(),octsyp1d)oubite tucetto0 sar Reacvlostool: voidlpublic function stopSignalReceived(string Snessage = 1*): void71OASOMОД100% KSa: 8- Thu 28 May 14:19:23© 2 /15 viewedAnaiunt approvaViewedpublic function pause(): void11 (1 Sthis->shallPause) (Sthis->shallPause = true;sthis->printMessage(sprintf(' --- Process $s PAUSED.', getaypid())):resume(): voidshallPause) (challPause = talselSthis->orintMessacelsorintt/'=e= Process fs RESIMED.". oetrvo1d0)))?public function markShallStop(): voidSthis->shallStop = true;ouniietunet ion markReadvtostool: votdSthise>readvToStoo = truelpublic function setMessage0nExit(?string Snessage = null): void...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
84046
|
2897
|
29
|
2026-05-28T11:19:21.496060+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967161496_m1.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
9203726579187570650
|
-6574314066069035822
|
typing_pause
|
hybrid
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
SlackFileEditViewGoHistoryWindowHelpDOCKERDOCKER (-zsh)2c55fe91ca4148a230e32eadocker_lamp_12026] No failed transcriptidocker_lamp_18. Stadocker_lamp_1205 Ddocker_lamp_1roc/1/fd/1'2>&1docker_lamp_12026ONEdocker_lamp_1 |Gracefully Stopping...Container docker-blackfContainer docker-mariadContainer kibanaStoppiContainer docker_lamp_1Container docker-jiminnContainer ngrok StoppinContainer docker-datadoContainer docker-datadoContainer docker-blackfContainer kibana StoppeContainer elasticsearchContainer docker-jiminnContainer elasticsearchmariadb-11 2026-0ownngrokt=2026pReq="{err: ‹nil>restarmariadb-12026-0ngrokt=2026on err=nilngrokt=2026f0743derr="reconnectinContainer docker_lamp_1Container ngrokError EContainer docker-mariadunexpected EOFerror during connect: Painers/ala97af7b5a28480What's next:Debug this Composelukas@Lukas-Kovaliks-MaV ALL VAULTS8My vaultExported%8All items* FavouritesBinV TYPESLoginCardIdentitySecure noteSSH keyFOLDERS+2FACSV Import 28.01.22LastPass Import 1.11.21NAS UsersSalesloftStarter KitNo folderCOLLECTIONSPersonal collectionMy vaultSendQ [URL_WITH_CREDENTIALS] mJ2STigExRjaUT^BoFy8NFEDOhttps://blog.whitelabeltechnologies....J2STigExRjaUT^BoFy8NFEDOhttps://www.rescuetime.com/log...XDLHx3m/Vangseyhttps://www.rescuetime.com/login?https://www.outsourcely.com/log..mLkl1230Shttps://www.outsourcely.com/login/Lkl1230Shttps://www.martinus.sk/login/?r..mLkl123Mhttps://www.martinus.sk/login/?redi..Lk/123Mhttps://www.jefit.com/login/m141122+HomeDMsActivityFilesLaterMore+ED→Jiminny ...# engineering# general# happy_birthday& infosec_internal_all# infra-changes#infrastructure_dev# jbu-team-info# jiminny-bg# platform-team# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of jimi...Direct messagesEo Vasil Vasilev •o Stoyan TomovLo lliyana Netseva&. Petko Kashinski®. Galya Dimitrovaa. Stefka Stoyanova* Todor Stamatov&. Steliyan Georgiev@ Vesg. Mira100% C8• Thu 28 May 14:19:21Describe what you are looking for# engineering8 246 0• MessagesP CanvasC FilesMore v+Friday, May 22nd"potchas" in AW'S MacWnen you arocateo a Deokatco host lor wacouteserroa prynes wocwocnne dAnm allocation period (typically 24 hours)|3 replies Last reply 6 days agoSaturday, May 23rd ~Ves 5:46 PMHey team,PHP 8.5 release is live. After the holidays fetch thelatest dev docker image to make sure you have the8.5.5 runtime locally.нннь 23Today ~Vasil Vasilev Ol 2:07 PMAction failed with error: SDK executionerror: Error: Claude Code returned an errorresult: API Error: 400 You have reached yourspecified API usage limits. You will regainaccess on 2026-06-01 at 00:00 UTC.I exhausted up all review tokensMessage #engineering......
|
84044
|
NULL
|
NULL
|
NULL
|
|
84045
|
2898
|
40
|
2026-05-28T11:19:18.517588+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967158517_m2.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
rircroxViewhsttonooonnsinePotLe.WindowHelp= github rircroxViewhsttonooonnsinePotLe.WindowHelp= github.com/~ Google GeminiPipelines - jiminny/appGemini 3.1 Pro ~* (JY-20613) Allow owner's role to tText relayDeleted object errorxUewredtines on New codJY-20963 fix deleted object impsJiminny\Exceptions(EmailActivityfrM Inbox (1,733) - lukas.kovalik@jiminioonre Reso ve php 81.15 ded8 Jiminm,Platform Sorint 5.02 - Platform Te8 Jiminny7 (SRD-6881] (On demand) TransSona Strbramaal an at 27/05/2021O Illyana Netsova at 27/05/2026, 18Jy 20910 schedule parallel upc X3c503006111478686b8441263e32426fefdfbe6fe27c8271e2c3acbignore tests for now. Just focus on non test filesTd be nappy to review the implementation code, but the git dim you provided only contains changesto a single test file: UpdateProcessManagerTest.php.Because the actual source files (such as (UpdateProcessManager.php orReindexTargetStatsReporter.php ) are not included in the snippet, I cannot analyze them forpotential issues.If you provide the code or the diff for the non-test files, I will gladly review them for logic flaws,architectural risks, or pertormance concerns.I1 OpenJy 20910 schedule parallel uodate target processing 812 130All commits - | Vasil-Jiminny wants to merge 65 commits into naster from JY-20910-schedule-parallel-update-target-processingCFilter tec.app/Traits/GracefullyStoppable.php ÷~ & app~ Ei Component/ESEntityTypeReindexer.phpReindexTargetStatsReporter,p...UpdateProcessManager.phpv Console~ #i Commands/ElasticsearchAsyncUpdateEsEntities.php•1AsvncUodateSupervisor.ohoDeleteEmailDocumentsCom…ReindexEntityTypes.php•1 RemoveGhostParticipantsCo….ResetAsyncElasticSearchCo...Đ Kernel.php~ # Contracts/ESStopSignallnterface.php~ Ei TraitsP GracefullvStonoable.oho~ Ei tests/Unit/Component/ESEntityTypeReindexerTest.phpReindexTargetStatsReporterTes…® UpdateProcessManagerTest.phpdie();public function pausel: voidstns-oshalPausecihneosthnllPanta = tmuessthseornuissaocsprintf(Hostnase "s pid is paused.gethostnane(),oelGvooouoocTunceion tesubel: vord11 (Sthis->shallPause)Sthis-schallPause = talse.sthis->orantvessaoeusprintf(hos hasoosressoscetboctaeAloctsypid)REview PR, be very detailed and tyr to find potential issues and bottlenecks, Iffounf return the location (file and line)00 в0.Yor lim nou chate teho' uend to imnrmy our moddle Camialie 411t can mata mttnkae co donbls chact" Yoir orhacy & CaminSummarize pageoubite tucetto0 sar Readvtostool: woralSthie-areadvToStoo & truedpublic function stopSignalReceived(string Snessage = **): void* :70 +7185 +QSOMOX 100%K3 8• Thu 28 May 14:19:130 2/15 viewedAwaiting approvalbmit review -+44 -43 BB00 Viewedpublie function pauset): votad11 (1 Sthis->shallPause) (Sthis->shallPause = true;sthis->printMessage(sprintf(' --- Process $s PAUSED.', getaypid())):public function resune(): voidif (Sthis->shallPause) (Sthis->shallPause = false;Sthis->orintMessacelsorintt/'=e= Process fs RESIMED.". oetrvo1d0)))?publie function markShall5topt): vosdSthis->shallStop = true;puslic function markleadylostopl); volSthise>readvToStoo = truelpublic function setMessage0nExit(?string Snessage = null): void...
|
NULL
|
9123395047144094862
|
NULL
|
click
|
ocr
|
NULL
|
rircroxViewhsttonooonnsinePotLe.WindowHelp= github rircroxViewhsttonooonnsinePotLe.WindowHelp= github.com/~ Google GeminiPipelines - jiminny/appGemini 3.1 Pro ~* (JY-20613) Allow owner's role to tText relayDeleted object errorxUewredtines on New codJY-20963 fix deleted object impsJiminny\Exceptions(EmailActivityfrM Inbox (1,733) - lukas.kovalik@jiminioonre Reso ve php 81.15 ded8 Jiminm,Platform Sorint 5.02 - Platform Te8 Jiminny7 (SRD-6881] (On demand) TransSona Strbramaal an at 27/05/2021O Illyana Netsova at 27/05/2026, 18Jy 20910 schedule parallel upc X3c503006111478686b8441263e32426fefdfbe6fe27c8271e2c3acbignore tests for now. Just focus on non test filesTd be nappy to review the implementation code, but the git dim you provided only contains changesto a single test file: UpdateProcessManagerTest.php.Because the actual source files (such as (UpdateProcessManager.php orReindexTargetStatsReporter.php ) are not included in the snippet, I cannot analyze them forpotential issues.If you provide the code or the diff for the non-test files, I will gladly review them for logic flaws,architectural risks, or pertormance concerns.I1 OpenJy 20910 schedule parallel uodate target processing 812 130All commits - | Vasil-Jiminny wants to merge 65 commits into naster from JY-20910-schedule-parallel-update-target-processingCFilter tec.app/Traits/GracefullyStoppable.php ÷~ & app~ Ei Component/ESEntityTypeReindexer.phpReindexTargetStatsReporter,p...UpdateProcessManager.phpv Console~ #i Commands/ElasticsearchAsyncUpdateEsEntities.php•1AsvncUodateSupervisor.ohoDeleteEmailDocumentsCom…ReindexEntityTypes.php•1 RemoveGhostParticipantsCo….ResetAsyncElasticSearchCo...Đ Kernel.php~ # Contracts/ESStopSignallnterface.php~ Ei TraitsP GracefullvStonoable.oho~ Ei tests/Unit/Component/ESEntityTypeReindexerTest.phpReindexTargetStatsReporterTes…® UpdateProcessManagerTest.phpdie();public function pausel: voidstns-oshalPausecihneosthnllPanta = tmuessthseornuissaocsprintf(Hostnase "s pid is paused.gethostnane(),oelGvooouoocTunceion tesubel: vord11 (Sthis->shallPause)Sthis-schallPause = talse.sthis->orantvessaoeusprintf(hos hasoosressoscetboctaeAloctsypid)REview PR, be very detailed and tyr to find potential issues and bottlenecks, Iffounf return the location (file and line)00 в0.Yor lim nou chate teho' uend to imnrmy our moddle Camialie 411t can mata mttnkae co donbls chact" Yoir orhacy & CaminSummarize pageoubite tucetto0 sar Readvtostool: woralSthie-areadvToStoo & truedpublic function stopSignalReceived(string Snessage = **): void* :70 +7185 +QSOMOX 100%K3 8• Thu 28 May 14:19:130 2/15 viewedAwaiting approvalbmit review -+44 -43 BB00 Viewedpublie function pauset): votad11 (1 Sthis->shallPause) (Sthis->shallPause = true;sthis->printMessage(sprintf(' --- Process $s PAUSED.', getaypid())):public function resune(): voidif (Sthis->shallPause) (Sthis->shallPause = false;Sthis->orintMessacelsorintt/'=e= Process fs RESIMED.". oetrvo1d0)))?publie function markShall5topt): vosdSthis->shallStop = true;puslic function markleadylostopl); volSthise>readvToStoo = truelpublic function setMessage0nExit(?string Snessage = null): void...
|
84043
|
NULL
|
NULL
|
NULL
|
|
84044
|
2897
|
28
|
2026-05-28T11:19:18.413691+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967158413_m1.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
SlackFileEditViewGoHistoryWindowHelpDOCKERDOCKER ( SlackFileEditViewGoHistoryWindowHelpDOCKERDOCKER (-zsh)2c55fe91ca4148a230e32eadocker_lamp_12026] No failed transcriptidocker_lamp_18? Stadocker_lamp_1205 Ddocker_lamp_1roc/1/fd/1'2>&1docker_lamp_12026ONEdocker_lamp_1 |Gracefully Stopping...Container docker-blackfContainer docker-mariadContainer kibanaStoppiContainer docker_lamp_1Container docker-jiminnContainer ngrok StoppinContainer docker-datadoContainer docker-datadoContainer docker-blackfContainer kibana StoppeContainer elasticsearchContainer docker-jiminnContainer elasticsearchmariadb-11 2026-0ownngrokt=2026pReq="{err: ‹nil>restarmariadb-12026-0ngrokt=2026on err=nilngrokt=2026f0743derr="reconnectinContainer docker_lamp_1Container ngrokError EContainer docker-mariadunexpected EOFerror during connect: Painers/ala97af7b5a28480What's next:Debug this Composelukas@Lukas-Kovaliks-MaV ALL VAULTS8My vaultExported%8All items* FavouritesBinV TYPESLoginCardIdentitySecure noteSSH keyFOLDERS+2FACSV Import 28.01.22LastPass Import 1.11.21NAS UsersSalesloftStarter KitNo folderCOLLECTIONSPersonal collectionMy vaultSendQ [URL_WITH_CREDENTIALS] mJ2STigExRjaUT^BoFy8NFEDOhttps://blog.whitelabeltechnologies....J2STigExRjaUT^BoFy8NFEDOhttps://www.rescuetime.com/log...XDLHx3m/Vangseyhttps://www.rescuetime.com/login?https://www.outsourcely.com/log..mLkl1230Shttps://www.outsourcely.com/login/Lkl1230Shttps://www.martinus.sk/login/?r..mLkl123Mhttps://www.martinus.sk/login/?redi..Lk/123Mhttps://www.jefit.com/login/m141122+HomeDMsActivityFilesLaterMore+ED→Jiminny ...# engineering# general# happy_birthday& infosec_internal_all# infra-changes#infrastructure_dev# jbu-team-info# jiminny-bg# platform-team# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of jimi...Direct messageso Vasil Vasilev 0o Stoyan TomovLo lliyana Netseva&. Petko Kashinski®. Galya Dimitrovaa. Stefka Stoyanova* Todor Stamatov&. Steliyan Georgiev. Vesg. Mira100% C8• Thu 28 May 14:19:16Describe what you are looking for# engineering8 246 0• MessagesP CanvasC FilesMore v+Friday, May 22nd"potchas" in AW'S MacWnen you arocateo a Deokatco host lor wacouteserroaprynes wocwcnre dAnm allocation period (typically 24 hours)|3 replies Last reply 6 days agoSaturday, May 23rd ~Ves 5:46 PMHey team,PHP 8.5 release is live. After the holidays fetch thelatest dev docker image to make sure you have the8.5.5 runtime locally.нннь 23Today ~Vasil Vasilev Ol 2:07 PMAction failed with error: SDK executionerror: Error: Claude Code returned an errorresult: API Error: 400 You have reached yourspecified API usage limits. You will regainaccess on 2026-06-01 at 00:00 UTC.I exhausted up all review tokensMessage #engineering......
|
NULL
|
-5452716165362498555
|
NULL
|
click
|
ocr
|
NULL
|
SlackFileEditViewGoHistoryWindowHelpDOCKERDOCKER ( SlackFileEditViewGoHistoryWindowHelpDOCKERDOCKER (-zsh)2c55fe91ca4148a230e32eadocker_lamp_12026] No failed transcriptidocker_lamp_18? Stadocker_lamp_1205 Ddocker_lamp_1roc/1/fd/1'2>&1docker_lamp_12026ONEdocker_lamp_1 |Gracefully Stopping...Container docker-blackfContainer docker-mariadContainer kibanaStoppiContainer docker_lamp_1Container docker-jiminnContainer ngrok StoppinContainer docker-datadoContainer docker-datadoContainer docker-blackfContainer kibana StoppeContainer elasticsearchContainer docker-jiminnContainer elasticsearchmariadb-11 2026-0ownngrokt=2026pReq="{err: ‹nil>restarmariadb-12026-0ngrokt=2026on err=nilngrokt=2026f0743derr="reconnectinContainer docker_lamp_1Container ngrokError EContainer docker-mariadunexpected EOFerror during connect: Painers/ala97af7b5a28480What's next:Debug this Composelukas@Lukas-Kovaliks-MaV ALL VAULTS8My vaultExported%8All items* FavouritesBinV TYPESLoginCardIdentitySecure noteSSH keyFOLDERS+2FACSV Import 28.01.22LastPass Import 1.11.21NAS UsersSalesloftStarter KitNo folderCOLLECTIONSPersonal collectionMy vaultSendQ [URL_WITH_CREDENTIALS] mJ2STigExRjaUT^BoFy8NFEDOhttps://blog.whitelabeltechnologies....J2STigExRjaUT^BoFy8NFEDOhttps://www.rescuetime.com/log...XDLHx3m/Vangseyhttps://www.rescuetime.com/login?https://www.outsourcely.com/log..mLkl1230Shttps://www.outsourcely.com/login/Lkl1230Shttps://www.martinus.sk/login/?r..mLkl123Mhttps://www.martinus.sk/login/?redi..Lk/123Mhttps://www.jefit.com/login/m141122+HomeDMsActivityFilesLaterMore+ED→Jiminny ...# engineering# general# happy_birthday& infosec_internal_all# infra-changes#infrastructure_dev# jbu-team-info# jiminny-bg# platform-team# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of jimi...Direct messageso Vasil Vasilev 0o Stoyan TomovLo lliyana Netseva&. Petko Kashinski®. Galya Dimitrovaa. Stefka Stoyanova* Todor Stamatov&. Steliyan Georgiev. Vesg. Mira100% C8• Thu 28 May 14:19:16Describe what you are looking for# engineering8 246 0• MessagesP CanvasC FilesMore v+Friday, May 22nd"potchas" in AW'S MacWnen you arocateo a Deokatco host lor wacouteserroaprynes wocwcnre dAnm allocation period (typically 24 hours)|3 replies Last reply 6 days agoSaturday, May 23rd ~Ves 5:46 PMHey team,PHP 8.5 release is live. After the holidays fetch thelatest dev docker image to make sure you have the8.5.5 runtime locally.нннь 23Today ~Vasil Vasilev Ol 2:07 PMAction failed with error: SDK executionerror: Error: Claude Code returned an errorresult: API Error: 400 You have reached yourspecified API usage limits. You will regainaccess on 2026-06-01 at 00:00 UTC.I exhausted up all review tokensMessage #engineering......
|
NULL
|
NULL
|
NULL
|
NULL
|
|
84043
|
2898
|
39
|
2026-05-28T11:19:11.569887+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967151569_m2.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.11402926,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.27055067,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.28172386,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.37988827,"width":0.09740692,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"bounds":{"left":0.0,"top":0.40143654,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.41260973,"width":0.08543883,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.43415803,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.44533122,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0,"top":0.4668795,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.47805268,"width":0.10106383,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"bounds":{"left":0.0028257978,"top":0.5047885,"width":0.036070477,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0028257978,"top":0.528332,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015957447,"top":0.5395052,"width":0.013297873,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.0028257978,"top":0.56105345,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"bounds":{"left":0.015957447,"top":0.57222664,"width":0.1271609,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.5937749,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.6049481,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.62649643,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.63766956,"width":0.12134308,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.6592179,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.6703911,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.69193935,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.70311254,"width":0.18201463,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.06732048,"top":0.69912213,"width":0.007978723,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.0028257978,"top":0.72625697,"width":0.07413564,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"bounds":{"left":0.0028257978,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"bounds":{"left":0.013796543,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"bounds":{"left":0.024933511,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"bounds":{"left":0.036070477,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"bounds":{"left":0.04720745,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"AI Chat settings","depth":3,"bounds":{"left":0.35854387,"top":0.055067837,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":3,"bounds":{"left":0.37051198,"top":0.055067837,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Main menu","depth":5,"bounds":{"left":0.08228058,"top":0.09736632,"width":0.015957447,"height":0.03830806},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open mode picker, currently 3.1 Pro","depth":6,"bounds":{"left":0.09823803,"top":0.10694334,"width":0.047539894,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Gemini","depth":13,"bounds":{"left":0.1022274,"top":0.10853951,"width":0.017121011,"height":0.016360734},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"3.1 Pro","depth":11,"bounds":{"left":0.12084442,"top":0.10853951,"width":0.013796543,"height":0.015961692},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Chat","depth":5,"bounds":{"left":0.35854387,"top":0.10215483,"width":0.011968086,"height":0.028731046},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open menu for conversation actions.","depth":5,"bounds":{"left":0.37051198,"top":0.10215483,"width":0.011968086,"height":0.028731046},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Conversation with Gemini","depth":7,"bounds":{"left":0.079288565,"top":0.14445332,"width":0.0003324468,"height":0.0007980846},"on_screen":true,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Conversation with Gemini","depth":8,"bounds":{"left":0.079288565,"top":0.14684756,"width":0.1200133,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":13,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"You said","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.","depth":15,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Expand","depth":13,"on_screen":false,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
-5954009690915080277
|
-3259026032374026076
|
typing_pause
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
84042
|
2897
|
27
|
2026-05-28T11:19:11.468643+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967151468_m1.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"AI Chat settings","depth":3,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":3,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Main menu","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open mode picker, currently 3.1 Pro","depth":6,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Gemini","depth":13,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"3.1 Pro","depth":11,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Chat","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open menu for conversation actions.","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Conversation with Gemini","depth":7,"on_screen":true,"help_text":"","role_description":"heading","subrole":"AXUnknown"}]...
|
-5638926396939739674
|
-3106536994015742749
|
typing_pause
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini...
|
84041
|
NULL
|
NULL
|
NULL
|
|
84041
|
2897
|
26
|
2026-05-28T11:19:09.128745+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967149128_m1.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"AI Chat settings","depth":3,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":3,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Main menu","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open mode picker, currently 3.1 Pro","depth":6,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
4333739136906508205
|
-3106538913866124061
|
typing_pause
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
84040
|
2898
|
38
|
2026-05-28T11:19:09.021426+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967149021_m2.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.11402926,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.27055067,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.28172386,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.37988827,"width":0.09740692,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"bounds":{"left":0.0,"top":0.40143654,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.41260973,"width":0.08543883,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.43415803,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.44533122,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0,"top":0.4668795,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.47805268,"width":0.10106383,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"bounds":{"left":0.0028257978,"top":0.5047885,"width":0.036070477,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0028257978,"top":0.528332,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015957447,"top":0.5395052,"width":0.013297873,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.0028257978,"top":0.56105345,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"bounds":{"left":0.015957447,"top":0.57222664,"width":0.1271609,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.5937749,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.6049481,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.62649643,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.63766956,"width":0.12134308,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.6592179,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.6703911,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.69193935,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.70311254,"width":0.18201463,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.06732048,"top":0.69912213,"width":0.007978723,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.0028257978,"top":0.72625697,"width":0.07413564,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"bounds":{"left":0.0028257978,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"bounds":{"left":0.013796543,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"bounds":{"left":0.024933511,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
-8478200795328864393
|
-3106541392062253853
|
typing_pause
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices...
|
84038
|
NULL
|
NULL
|
NULL
|
|
84039
|
2897
|
25
|
2026-05-28T11:19:07.219829+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967147219_m1.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"AI Chat settings","depth":3,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":3,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
426904441491657512
|
-3105408620207737629
|
typing_pause
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close...
|
84037
|
NULL
|
NULL
|
NULL
|
|
84038
|
2898
|
37
|
2026-05-28T11:19:07.107978+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967147107_m2.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.11402926,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.27055067,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.28172386,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.37988827,"width":0.09740692,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"bounds":{"left":0.0,"top":0.40143654,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.41260973,"width":0.08543883,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.43415803,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.44533122,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0,"top":0.4668795,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.47805268,"width":0.10106383,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"bounds":{"left":0.0028257978,"top":0.5047885,"width":0.036070477,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0028257978,"top":0.528332,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015957447,"top":0.5395052,"width":0.013297873,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.0028257978,"top":0.56105345,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"bounds":{"left":0.015957447,"top":0.57222664,"width":0.1271609,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.5937749,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.6049481,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.62649643,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.63766956,"width":0.12134308,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.6592179,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.6703911,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.69193935,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.70311254,"width":0.18201463,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.06732048,"top":0.69912213,"width":0.007978723,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.0028257978,"top":0.72625697,"width":0.07413564,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"bounds":{"left":0.0028257978,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"bounds":{"left":0.013796543,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"bounds":{"left":0.024933511,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"bounds":{"left":0.036070477,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"bounds":{"left":0.04720745,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"AI Chat settings","depth":3,"bounds":{"left":0.35854387,"top":0.055067837,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":3,"bounds":{"left":0.37051198,"top":0.055067837,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Main menu","depth":5,"bounds":{"left":0.08228058,"top":0.09736632,"width":0.015957447,"height":0.03830806},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
4066070249281182066
|
-3106538918161615645
|
typing_pause
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
84037
|
2897
|
24
|
2026-05-28T11:19:04.952998+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967144952_m1.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected....
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"AI Chat settings","depth":3,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":3,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Main menu","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open mode picker, currently 3.1 Pro","depth":6,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Gemini","depth":13,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"3.1 Pro","depth":11,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Chat","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open menu for conversation actions.","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Conversation with Gemini","depth":7,"on_screen":true,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Conversation with Gemini","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":13,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"You said","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.","depth":15,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
-2841637628066877512
|
-3403141220450930556
|
typing_pause
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected....
|
NULL
|
NULL
|
NULL
|
NULL
|
|
84036
|
2898
|
36
|
2026-05-28T11:19:04.840567+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967144840_m2.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.11402926,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.27055067,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.28172386,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.37988827,"width":0.09740692,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"bounds":{"left":0.0,"top":0.40143654,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.41260973,"width":0.08543883,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.43415803,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.44533122,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0,"top":0.4668795,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.47805268,"width":0.10106383,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"bounds":{"left":0.0028257978,"top":0.5047885,"width":0.036070477,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0028257978,"top":0.528332,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015957447,"top":0.5395052,"width":0.013297873,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.0028257978,"top":0.56105345,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"bounds":{"left":0.015957447,"top":0.57222664,"width":0.1271609,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.5937749,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.6049481,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.62649643,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.63766956,"width":0.12134308,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.6592179,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.6703911,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.69193935,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.70311254,"width":0.18201463,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.06732048,"top":0.69912213,"width":0.007978723,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.0028257978,"top":0.72625697,"width":0.07413564,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"bounds":{"left":0.0028257978,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
5186100790533387229
|
-3106541390988512029
|
typing_pause
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar...
|
84035
|
NULL
|
NULL
|
NULL
|
|
84035
|
2898
|
35
|
2026-05-28T11:19:02.485651+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967142485_m2.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:
Structural and Dependency Changes
Structural and Dependency Changes
Replaced Datadog:...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.11402926,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.27055067,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.28172386,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.37988827,"width":0.09740692,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"bounds":{"left":0.0,"top":0.40143654,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.41260973,"width":0.08543883,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.43415803,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.44533122,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0,"top":0.4668795,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.47805268,"width":0.10106383,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"bounds":{"left":0.0028257978,"top":0.5047885,"width":0.036070477,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0028257978,"top":0.528332,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015957447,"top":0.5395052,"width":0.013297873,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.0028257978,"top":0.56105345,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"bounds":{"left":0.015957447,"top":0.57222664,"width":0.1271609,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.5937749,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.6049481,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.62649643,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.63766956,"width":0.12134308,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.6592179,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.6703911,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.69193935,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.70311254,"width":0.18201463,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.06732048,"top":0.69912213,"width":0.007978723,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.0028257978,"top":0.72625697,"width":0.07413564,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"bounds":{"left":0.0028257978,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"bounds":{"left":0.013796543,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"bounds":{"left":0.024933511,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"bounds":{"left":0.036070477,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"bounds":{"left":0.04720745,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"AI Chat settings","depth":3,"bounds":{"left":0.35854387,"top":0.055067837,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":3,"bounds":{"left":0.37051198,"top":0.055067837,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Main menu","depth":5,"bounds":{"left":0.08228058,"top":0.09736632,"width":0.015957447,"height":0.03830806},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open mode picker, currently 3.1 Pro","depth":6,"bounds":{"left":0.09823803,"top":0.10694334,"width":0.047539894,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Gemini","depth":13,"bounds":{"left":0.1022274,"top":0.10853951,"width":0.017121011,"height":0.016360734},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"3.1 Pro","depth":11,"bounds":{"left":0.12084442,"top":0.10853951,"width":0.013796543,"height":0.015961692},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Chat","depth":5,"bounds":{"left":0.35854387,"top":0.10215483,"width":0.011968086,"height":0.028731046},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open menu for conversation actions.","depth":5,"bounds":{"left":0.37051198,"top":0.10215483,"width":0.011968086,"height":0.028731046},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Conversation with Gemini","depth":7,"bounds":{"left":0.079288565,"top":0.14445332,"width":0.0003324468,"height":0.0007980846},"on_screen":true,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Conversation with Gemini","depth":8,"bounds":{"left":0.079288565,"top":0.14684756,"width":0.1200133,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":13,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"You said","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.","depth":15,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Expand","depth":13,"on_screen":false,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Copy prompt","depth":12,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Gemini said","depth":12,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Gemini said","depth":13,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Here is a summary of the changes in the provided git diff for","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"UpdateProcessManagerTest.php","depth":17,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":":","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Structural and Dependency Changes","depth":15,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Structural and Dependency Changes","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Replaced Datadog:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
4171954087964796239
|
-3259026032374026108
|
typing_pause
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:
Structural and Dependency Changes
Structural and Dependency Changes
Replaced Datadog:...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
84034
|
2897
|
23
|
2026-05-28T11:19:01.363149+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967141363_m1.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:
Structural and Dependency Changes
Structural and Dependency Changes
Replaced Datadog:
Removed the
ChaseConey\LaravelDatadogHelper\Datadog
dependency and replaced it with
Jiminny\Component\ES\ReindexTargetStatsReporter
.
Added Constants and Properties:
Introduced a new
ENVIRONMENT
constant (set to
'testing'
) and a
$statsReporter
property to hold the mock for the new stats reporter....
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"AI Chat settings","depth":3,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":3,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Main menu","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open mode picker, currently 3.1 Pro","depth":6,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Gemini","depth":13,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"3.1 Pro","depth":11,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Chat","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open menu for conversation actions.","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Conversation with Gemini","depth":7,"on_screen":true,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Conversation with Gemini","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":13,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"You said","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.","depth":15,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Expand","depth":13,"on_screen":false,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Copy prompt","depth":12,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Gemini said","depth":12,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Gemini said","depth":13,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Here is a summary of the changes in the provided git diff for","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"UpdateProcessManagerTest.php","depth":17,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":":","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Structural and Dependency Changes","depth":15,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Structural and Dependency Changes","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Replaced Datadog:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Removed the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ChaseConey\\LaravelDatadogHelper\\Datadog","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"dependency and replaced it with","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Jiminny\\Component\\ES\\ReindexTargetStatsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":".","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Added Constants and Properties:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Introduced a new","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ENVIRONMENT","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"constant (set to","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"'testing'","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":") and a","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"$statsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"property to hold the mock for the new stats reporter.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
4179630964884368970
|
-3250018833119285116
|
typing_pause
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:
Structural and Dependency Changes
Structural and Dependency Changes
Replaced Datadog:
Removed the
ChaseConey\LaravelDatadogHelper\Datadog
dependency and replaced it with
Jiminny\Component\ES\ReindexTargetStatsReporter
.
Added Constants and Properties:
Introduced a new
ENVIRONMENT
constant (set to
'testing'
) and a
$statsReporter
property to hold the mock for the new stats reporter....
|
84032
|
NULL
|
NULL
|
NULL
|
|
84033
|
2898
|
34
|
2026-05-28T11:19:00.656806+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967140656_m2.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:
Structural and Dependency Changes
Structural and Dependency Changes
Replaced Datadog:
Removed the
ChaseConey\LaravelDatadogHelper\Datadog
dependency and replaced it with
Jiminny\Component\ES\ReindexTargetStatsReporter
.
Added Constants and Properties:
Introduced a new
ENVIRONMENT
constant (set to
'testing'
) and a
$statsReporter...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.11402926,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.27055067,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.28172386,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.37988827,"width":0.09740692,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"bounds":{"left":0.0,"top":0.40143654,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.41260973,"width":0.08543883,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.43415803,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.44533122,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0,"top":0.4668795,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.47805268,"width":0.10106383,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"bounds":{"left":0.0028257978,"top":0.5047885,"width":0.036070477,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0028257978,"top":0.528332,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015957447,"top":0.5395052,"width":0.013297873,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.0028257978,"top":0.56105345,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"bounds":{"left":0.015957447,"top":0.57222664,"width":0.1271609,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.5937749,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.6049481,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.62649643,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.63766956,"width":0.12134308,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.6592179,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.6703911,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.69193935,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.70311254,"width":0.18201463,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.06732048,"top":0.69912213,"width":0.007978723,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.0028257978,"top":0.72625697,"width":0.07413564,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"bounds":{"left":0.0028257978,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"bounds":{"left":0.013796543,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"bounds":{"left":0.024933511,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"bounds":{"left":0.036070477,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"bounds":{"left":0.04720745,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"AI Chat settings","depth":3,"bounds":{"left":0.35854387,"top":0.055067837,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":3,"bounds":{"left":0.37051198,"top":0.055067837,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Main menu","depth":5,"bounds":{"left":0.08228058,"top":0.09736632,"width":0.015957447,"height":0.03830806},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open mode picker, currently 3.1 Pro","depth":6,"bounds":{"left":0.09823803,"top":0.10694334,"width":0.047539894,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Gemini","depth":13,"bounds":{"left":0.1022274,"top":0.10853951,"width":0.017121011,"height":0.016360734},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"3.1 Pro","depth":11,"bounds":{"left":0.12084442,"top":0.10853951,"width":0.013796543,"height":0.015961692},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Chat","depth":5,"bounds":{"left":0.35854387,"top":0.10215483,"width":0.011968086,"height":0.028731046},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open menu for conversation actions.","depth":5,"bounds":{"left":0.37051198,"top":0.10215483,"width":0.011968086,"height":0.028731046},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Conversation with Gemini","depth":7,"bounds":{"left":0.079288565,"top":0.14445332,"width":0.0003324468,"height":0.0007980846},"on_screen":true,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Conversation with Gemini","depth":8,"bounds":{"left":0.079288565,"top":0.14684756,"width":0.1200133,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":13,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"You said","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.","depth":15,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Expand","depth":13,"on_screen":false,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Copy prompt","depth":12,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Gemini said","depth":12,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Gemini said","depth":13,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Here is a summary of the changes in the provided git diff for","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"UpdateProcessManagerTest.php","depth":17,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":":","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Structural and Dependency Changes","depth":15,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Structural and Dependency Changes","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Replaced Datadog:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Removed the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ChaseConey\\LaravelDatadogHelper\\Datadog","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"dependency and replaced it with","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Jiminny\\Component\\ES\\ReindexTargetStatsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":".","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Added Constants and Properties:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Introduced a new","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ENVIRONMENT","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"constant (set to","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"'testing'","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":") and a","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"$statsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
8353329525708013500
|
-3259026032374026108
|
typing_pause
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:
Structural and Dependency Changes
Structural and Dependency Changes
Replaced Datadog:
Removed the
ChaseConey\LaravelDatadogHelper\Datadog
dependency and replaced it with
Jiminny\Component\ES\ReindexTargetStatsReporter
.
Added Constants and Properties:
Introduced a new
ENVIRONMENT
constant (set to
'testing'
) and a
$statsReporter...
|
84031
|
NULL
|
NULL
|
NULL
|
|
84032
|
2897
|
22
|
2026-05-28T11:19:00.221526+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967140221_m1.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"AI Chat settings","depth":3,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":3,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Main menu","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open mode picker, currently 3.1 Pro","depth":6,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Gemini","depth":13,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"3.1 Pro","depth":11,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Chat","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open menu for conversation actions.","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Conversation with Gemini","depth":7,"on_screen":true,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Conversation with Gemini","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
3104573187515416659
|
-3106536994015742749
|
typing_pause
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
84031
|
2898
|
33
|
2026-05-28T11:19:00.110488+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967140110_m2.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.11402926,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.27055067,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.28172386,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.37988827,"width":0.09740692,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"bounds":{"left":0.0,"top":0.40143654,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.41260973,"width":0.08543883,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.43415803,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.44533122,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0,"top":0.4668795,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.47805268,"width":0.10106383,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"bounds":{"left":0.0028257978,"top":0.5047885,"width":0.036070477,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0028257978,"top":0.528332,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015957447,"top":0.5395052,"width":0.013297873,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.0028257978,"top":0.56105345,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"bounds":{"left":0.015957447,"top":0.57222664,"width":0.1271609,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.5937749,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.6049481,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.62649643,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.63766956,"width":0.12134308,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.6592179,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.6703911,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.69193935,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.70311254,"width":0.18201463,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.06732048,"top":0.69912213,"width":0.007978723,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.0028257978,"top":0.72625697,"width":0.07413564,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"bounds":{"left":0.0028257978,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"bounds":{"left":0.013796543,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"bounds":{"left":0.024933511,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"bounds":{"left":0.036070477,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"bounds":{"left":0.04720745,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
-1860515063492607853
|
-3106536994015218461
|
typing_pause
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
84030
|
2898
|
32
|
2026-05-28T11:18:57.560761+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967137560_m2.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:
Structural and Dependency Changes
Structural and Dependency Changes
Replaced Datadog:
Removed the
ChaseConey\LaravelDatadogHelper\Datadog
dependency and replaced it with
Jiminny\Component\ES\ReindexTargetStatsReporter
.
Added Constants and Properties:
Introduced a new...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.11402926,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.27055067,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.28172386,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.37988827,"width":0.09740692,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"bounds":{"left":0.0,"top":0.40143654,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.41260973,"width":0.08543883,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.43415803,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.44533122,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0,"top":0.4668795,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.47805268,"width":0.10106383,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"bounds":{"left":0.0028257978,"top":0.5047885,"width":0.036070477,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0028257978,"top":0.528332,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015957447,"top":0.5395052,"width":0.013297873,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.0028257978,"top":0.56105345,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"bounds":{"left":0.015957447,"top":0.57222664,"width":0.1271609,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.5937749,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.6049481,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.62649643,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.63766956,"width":0.12134308,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.6592179,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.6703911,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.69193935,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.70311254,"width":0.18201463,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.06732048,"top":0.69912213,"width":0.007978723,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.0028257978,"top":0.72625697,"width":0.07413564,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"bounds":{"left":0.0028257978,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"bounds":{"left":0.013796543,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"bounds":{"left":0.024933511,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"bounds":{"left":0.036070477,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"bounds":{"left":0.04720745,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"AI Chat settings","depth":3,"bounds":{"left":0.35854387,"top":0.055067837,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":3,"bounds":{"left":0.37051198,"top":0.055067837,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Main menu","depth":5,"bounds":{"left":0.08228058,"top":0.09736632,"width":0.015957447,"height":0.03830806},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open mode picker, currently 3.1 Pro","depth":6,"bounds":{"left":0.09823803,"top":0.10694334,"width":0.047539894,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Gemini","depth":13,"bounds":{"left":0.1022274,"top":0.10853951,"width":0.017121011,"height":0.016360734},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"3.1 Pro","depth":11,"bounds":{"left":0.12084442,"top":0.10853951,"width":0.013796543,"height":0.015961692},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Chat","depth":5,"bounds":{"left":0.35854387,"top":0.10215483,"width":0.011968086,"height":0.028731046},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open menu for conversation actions.","depth":5,"bounds":{"left":0.37051198,"top":0.10215483,"width":0.011968086,"height":0.028731046},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Conversation with Gemini","depth":7,"bounds":{"left":0.079288565,"top":0.14445332,"width":0.0003324468,"height":0.0007980846},"on_screen":true,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Conversation with Gemini","depth":8,"bounds":{"left":0.079288565,"top":0.14684756,"width":0.1200133,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":13,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"You said","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.","depth":15,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Expand","depth":13,"on_screen":false,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Copy prompt","depth":12,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Gemini said","depth":12,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Gemini said","depth":13,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Here is a summary of the changes in the provided git diff for","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"UpdateProcessManagerTest.php","depth":17,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":":","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Structural and Dependency Changes","depth":15,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Structural and Dependency Changes","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Replaced Datadog:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Removed the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ChaseConey\\LaravelDatadogHelper\\Datadog","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"dependency and replaced it with","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Jiminny\\Component\\ES\\ReindexTargetStatsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":".","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Added Constants and Properties:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Introduced a new","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
-7263953255105206546
|
-3258463082420604796
|
typing_pause
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:
Structural and Dependency Changes
Structural and Dependency Changes
Replaced Datadog:
Removed the
ChaseConey\LaravelDatadogHelper\Datadog
dependency and replaced it with
Jiminny\Component\ES\ReindexTargetStatsReporter
.
Added Constants and Properties:
Introduced a new...
|
84027
|
NULL
|
NULL
|
NULL
|
|
84029
|
2897
|
21
|
2026-05-28T11:18:57.452134+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967137452_m1.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:
Structural and Dependency Changes
Structural and Dependency Changes
Replaced Datadog:
Removed the
ChaseConey\LaravelDatadogHelper\Datadog
dependency and replaced it with
Jiminny\Component\ES\ReindexTargetStatsReporter
.
Added Constants and Properties:
Introduced a new
ENVIRONMENT
constant (set to
'testing'
) and a
$statsReporter
property to hold the mock for the new stats reporter....
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"AI Chat settings","depth":3,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":3,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Main menu","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open mode picker, currently 3.1 Pro","depth":6,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Gemini","depth":13,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"3.1 Pro","depth":11,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Chat","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open menu for conversation actions.","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Conversation with Gemini","depth":7,"on_screen":true,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Conversation with Gemini","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":13,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"You said","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.","depth":15,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Expand","depth":13,"on_screen":false,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Copy prompt","depth":12,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Gemini said","depth":12,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Gemini said","depth":13,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Here is a summary of the changes in the provided git diff for","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"UpdateProcessManagerTest.php","depth":17,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":":","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Structural and Dependency Changes","depth":15,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Structural and Dependency Changes","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Replaced Datadog:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Removed the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ChaseConey\\LaravelDatadogHelper\\Datadog","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"dependency and replaced it with","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Jiminny\\Component\\ES\\ReindexTargetStatsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":".","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Added Constants and Properties:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Introduced a new","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ENVIRONMENT","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"constant (set to","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"'testing'","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":") and a","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"$statsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"property to hold the mock for the new stats reporter.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
4179630964884368970
|
-3250018833119285116
|
typing_pause
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:
Structural and Dependency Changes
Structural and Dependency Changes
Replaced Datadog:
Removed the
ChaseConey\LaravelDatadogHelper\Datadog
dependency and replaced it with
Jiminny\Component\ES\ReindexTargetStatsReporter
.
Added Constants and Properties:
Introduced a new
ENVIRONMENT
constant (set to
'testing'
) and a
$statsReporter
property to hold the mock for the new stats reporter....
|
84028
|
NULL
|
NULL
|
NULL
|
|
84028
|
2897
|
20
|
2026-05-28T11:18:55.050145+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967135050_m1.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:
Structural and Dependency Changes
Structural and Dependency Changes
Replaced Datadog:
Removed the
ChaseConey\LaravelDatadogHelper\Datadog
dependency and replaced it with
Jiminny\Component\ES\ReindexTargetStatsReporter
.
Added Constants and Properties:
Introduced a new
ENVIRONMENT
constant (set to
'testing'
) and a
$statsReporter
property to hold the mock for the new stats reporter.
Processor Instantiation:
Updated the
getProcessor()
method to inject the new
$statsReporter
mock into the
UpdateProcessManager
and utilize the
ENVIRONMENT
constant.
Test Case Modifications
Test Case Modifications
Removed Memory Logging Tests:
Deleted
testLogMemoryUsageEmitsGaugeWhenLockIsAbsent
and
testLogMemoryUsageSkipsGaugeWhenLockIsPresent
entirely, as the Redis lock and Datadog gauge logic were removed.
Added Empty Selection Test:
Introduced
testEmptySelectionLogsAndReturnsFalse
to verify that processing an empty selection logs a debug message, skips batch manager operations (
generateName
,
scheduleWork
,
finishWork
), skips the stats reporter, and cleanly returns
false
.
Updated Existing Tests:
Modified
testRunUpdate
and
testRunDoUpdateButThrottled
to assert that the
$statsReporter->report()
method is called and to utilize the updated status manager mock.
Helper Method Refactoring
Helper Method Refactoring
Dynamic Status Manager Assertions:
Updated the
prepareStatusManager(int $invokeTimes = 0)
method to accept an integer. This allows tests to dynamically assert exactly how many times methods like
generateName
,
setUpdateTarget
,
scheduleWork
, and
finishWork
are invoked.
Removed Obsolete Helpers:
Deleted the
prepareLogger()
and
silenceDatadogAndRedisLock()
helper methods, replacing their inline functionality with standard
Log::shouldReceive
expectations where needed....
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"AI Chat settings","depth":3,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":3,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Main menu","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open mode picker, currently 3.1 Pro","depth":6,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Gemini","depth":13,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"3.1 Pro","depth":11,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Chat","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open menu for conversation actions.","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Conversation with Gemini","depth":7,"on_screen":true,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Conversation with Gemini","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":13,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"You said","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.","depth":15,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Expand","depth":13,"on_screen":false,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Copy prompt","depth":12,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Gemini said","depth":12,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Gemini said","depth":13,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Here is a summary of the changes in the provided git diff for","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"UpdateProcessManagerTest.php","depth":17,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":":","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Structural and Dependency Changes","depth":15,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Structural and Dependency Changes","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Replaced Datadog:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Removed the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ChaseConey\\LaravelDatadogHelper\\Datadog","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"dependency and replaced it with","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Jiminny\\Component\\ES\\ReindexTargetStatsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":".","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Added Constants and Properties:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Introduced a new","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ENVIRONMENT","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"constant (set to","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"'testing'","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":") and a","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"$statsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"property to hold the mock for the new stats reporter.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Processor Instantiation:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Updated the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"getProcessor()","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"method to inject the new","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"$statsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"mock into the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"UpdateProcessManager","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"and utilize the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ENVIRONMENT","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"constant.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Test Case Modifications","depth":15,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Test Case Modifications","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Removed Memory Logging Tests:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Deleted","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testLogMemoryUsageEmitsGaugeWhenLockIsAbsent","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"and","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testLogMemoryUsageSkipsGaugeWhenLockIsPresent","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"entirely, as the Redis lock and Datadog gauge logic were removed.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Added Empty Selection Test:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Introduced","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testEmptySelectionLogsAndReturnsFalse","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"to verify that processing an empty selection logs a debug message, skips batch manager operations (","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"generateName","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":",","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"scheduleWork","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":",","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"finishWork","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"), skips the stats reporter, and cleanly returns","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"false","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":".","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Updated Existing Tests:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Modified","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testRunUpdate","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"and","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testRunDoUpdateButThrottled","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"to assert that the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"$statsReporter->report()","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"method is called and to utilize the updated status manager mock.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Helper Method Refactoring","depth":15,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Helper Method Refactoring","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Dynamic Status Manager Assertions:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Updated the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"prepareStatusManager(int $invokeTimes = 0)","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"method to accept an integer. This allows tests to dynamically assert exactly how many times methods like","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"generateName","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":",","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"setUpdateTarget","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":",","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"scheduleWork","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":", and","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"finishWork","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"are invoked.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Removed Obsolete Helpers:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Deleted the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"prepareLogger()","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"and","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"silenceDatadogAndRedisLock()","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"helper methods, replacing their inline functionality with standard","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Log::shouldReceive","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"expectations where needed.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
-6088725376102468982
|
-3114910844299218812
|
typing_pause
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:
Structural and Dependency Changes
Structural and Dependency Changes
Replaced Datadog:
Removed the
ChaseConey\LaravelDatadogHelper\Datadog
dependency and replaced it with
Jiminny\Component\ES\ReindexTargetStatsReporter
.
Added Constants and Properties:
Introduced a new
ENVIRONMENT
constant (set to
'testing'
) and a
$statsReporter
property to hold the mock for the new stats reporter.
Processor Instantiation:
Updated the
getProcessor()
method to inject the new
$statsReporter
mock into the
UpdateProcessManager
and utilize the
ENVIRONMENT
constant.
Test Case Modifications
Test Case Modifications
Removed Memory Logging Tests:
Deleted
testLogMemoryUsageEmitsGaugeWhenLockIsAbsent
and
testLogMemoryUsageSkipsGaugeWhenLockIsPresent
entirely, as the Redis lock and Datadog gauge logic were removed.
Added Empty Selection Test:
Introduced
testEmptySelectionLogsAndReturnsFalse
to verify that processing an empty selection logs a debug message, skips batch manager operations (
generateName
,
scheduleWork
,
finishWork
), skips the stats reporter, and cleanly returns
false
.
Updated Existing Tests:
Modified
testRunUpdate
and
testRunDoUpdateButThrottled
to assert that the
$statsReporter->report()
method is called and to utilize the updated status manager mock.
Helper Method Refactoring
Helper Method Refactoring
Dynamic Status Manager Assertions:
Updated the
prepareStatusManager(int $invokeTimes = 0)
method to accept an integer. This allows tests to dynamically assert exactly how many times methods like
generateName
,
setUpdateTarget
,
scheduleWork
, and
finishWork
are invoked.
Removed Obsolete Helpers:
Deleted the
prepareLogger()
and
silenceDatadogAndRedisLock()
helper methods, replacing their inline functionality with standard
Log::shouldReceive
expectations where needed....
|
NULL
|
NULL
|
NULL
|
NULL
|
|
84027
|
2898
|
31
|
2026-05-28T11:18:53.975645+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967133975_m2.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:
Structural and Dependency Changes
Structural and Dependency Changes
Replaced Datadog:
Removed the
ChaseConey\LaravelDatadogHelper\Datadog
dependency and replaced it with
Jiminny\Component\ES\ReindexTargetStatsReporter
.
Added Constants and Properties:
Introduced a new
ENVIRONMENT
constant (set to
'testing'
) and a
$statsReporter
property to hold the mock for the new stats reporter.
Processor Instantiation:
Updated the
getProcessor()
method to inject the new
$statsReporter
mock into the
UpdateProcessManager
and utilize the
ENVIRONMENT
constant.
Test Case Modifications
Test Case Modifications
Removed Memory Logging Tests:
Deleted
testLogMemoryUsageEmitsGaugeWhenLockIsAbsent
and
testLogMemoryUsageSkipsGaugeWhenLockIsPresent
entirely, as the Redis lock and Datadog gauge logic were removed.
Added Empty Selection Test:
Introduced
testEmptySelectionLogsAndReturnsFalse
to verify that processing an empty selection logs a debug message, skips batch manager operations (
generateName
,
scheduleWork
,
finishWork
), skips the stats reporter, and cleanly returns
false
.
Updated Existing Tests:
Modified
testRunUpdate
and
testRunDoUpdateButThrottled
to assert that the
$statsReporter->report()
method is called and to utilize the updated status manager mock.
Helper Method Refactoring
Helper Method Refactoring
Dynamic Status Manager Assertions:
Updated the
prepareStatusManager(int $invokeTimes = 0)
method to accept an integer. This allows tests to dynamically assert exactly how many times methods like
generateName
,
setUpdateTarget
,
scheduleWork
, and
finishWork
are invoked.
Removed Obsolete Helpers:
Deleted the
prepareLogger()...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.11402926,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.27055067,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.28172386,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.37988827,"width":0.09740692,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"bounds":{"left":0.0,"top":0.40143654,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.41260973,"width":0.08543883,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.43415803,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.44533122,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0,"top":0.4668795,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.47805268,"width":0.10106383,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"bounds":{"left":0.0028257978,"top":0.5047885,"width":0.036070477,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0028257978,"top":0.528332,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015957447,"top":0.5395052,"width":0.013297873,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.0028257978,"top":0.56105345,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"bounds":{"left":0.015957447,"top":0.57222664,"width":0.1271609,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.5937749,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.6049481,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.62649643,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.63766956,"width":0.12134308,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.6592179,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.6703911,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.69193935,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.70311254,"width":0.18201463,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.06732048,"top":0.69912213,"width":0.007978723,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.0028257978,"top":0.72625697,"width":0.07413564,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"bounds":{"left":0.0028257978,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"bounds":{"left":0.013796543,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"bounds":{"left":0.024933511,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"bounds":{"left":0.036070477,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"bounds":{"left":0.04720745,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"AI Chat settings","depth":3,"bounds":{"left":0.35854387,"top":0.055067837,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":3,"bounds":{"left":0.37051198,"top":0.055067837,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Main menu","depth":5,"bounds":{"left":0.08228058,"top":0.09736632,"width":0.015957447,"height":0.03830806},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open mode picker, currently 3.1 Pro","depth":6,"bounds":{"left":0.09823803,"top":0.10694334,"width":0.047539894,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Gemini","depth":13,"bounds":{"left":0.1022274,"top":0.10853951,"width":0.017121011,"height":0.016360734},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"3.1 Pro","depth":11,"bounds":{"left":0.12084442,"top":0.10853951,"width":0.013796543,"height":0.015961692},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Chat","depth":5,"bounds":{"left":0.35854387,"top":0.10215483,"width":0.011968086,"height":0.028731046},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open menu for conversation actions.","depth":5,"bounds":{"left":0.37051198,"top":0.10215483,"width":0.011968086,"height":0.028731046},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Conversation with Gemini","depth":7,"bounds":{"left":0.079288565,"top":0.14445332,"width":0.0003324468,"height":0.0007980846},"on_screen":true,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Conversation with Gemini","depth":8,"bounds":{"left":0.079288565,"top":0.14684756,"width":0.1200133,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":13,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"You said","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.","depth":15,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Expand","depth":13,"on_screen":false,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Copy prompt","depth":12,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Gemini said","depth":12,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Gemini said","depth":13,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Here is a summary of the changes in the provided git diff for","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"UpdateProcessManagerTest.php","depth":17,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":":","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Structural and Dependency Changes","depth":15,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Structural and Dependency Changes","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Replaced Datadog:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Removed the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ChaseConey\\LaravelDatadogHelper\\Datadog","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"dependency and replaced it with","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Jiminny\\Component\\ES\\ReindexTargetStatsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":".","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Added Constants and Properties:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Introduced a new","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ENVIRONMENT","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"constant (set to","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"'testing'","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":") and a","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"$statsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"property to hold the mock for the new stats reporter.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Processor Instantiation:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Updated the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"getProcessor()","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"method to inject the new","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"$statsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"mock into the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"UpdateProcessManager","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"and utilize the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ENVIRONMENT","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"constant.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Test Case Modifications","depth":15,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Test Case Modifications","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Removed Memory Logging Tests:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Deleted","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testLogMemoryUsageEmitsGaugeWhenLockIsAbsent","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"and","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testLogMemoryUsageSkipsGaugeWhenLockIsPresent","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"entirely, as the Redis lock and Datadog gauge logic were removed.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Added Empty Selection Test:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Introduced","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testEmptySelectionLogsAndReturnsFalse","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"to verify that processing an empty selection logs a debug message, skips batch manager operations (","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"generateName","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":",","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"scheduleWork","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":",","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"finishWork","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"), skips the stats reporter, and cleanly returns","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"false","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":".","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Updated Existing Tests:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Modified","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testRunUpdate","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"and","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testRunDoUpdateButThrottled","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"to assert that the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"$statsReporter->report()","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"method is called and to utilize the updated status manager mock.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Helper Method Refactoring","depth":15,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Helper Method Refactoring","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Dynamic Status Manager Assertions:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Updated the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"prepareStatusManager(int $invokeTimes = 0)","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"method to accept an integer. This allows tests to dynamically assert exactly how many times methods like","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"generateName","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":",","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"setUpdateTarget","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":",","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"scheduleWork","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":", and","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"finishWork","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"are invoked.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Removed Obsolete Helpers:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Deleted the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"prepareLogger()","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
-7373748454715904801
|
-3403141220449881980
|
typing_pause
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:
Structural and Dependency Changes
Structural and Dependency Changes
Replaced Datadog:
Removed the
ChaseConey\LaravelDatadogHelper\Datadog
dependency and replaced it with
Jiminny\Component\ES\ReindexTargetStatsReporter
.
Added Constants and Properties:
Introduced a new
ENVIRONMENT
constant (set to
'testing'
) and a
$statsReporter
property to hold the mock for the new stats reporter.
Processor Instantiation:
Updated the
getProcessor()
method to inject the new
$statsReporter
mock into the
UpdateProcessManager
and utilize the
ENVIRONMENT
constant.
Test Case Modifications
Test Case Modifications
Removed Memory Logging Tests:
Deleted
testLogMemoryUsageEmitsGaugeWhenLockIsAbsent
and
testLogMemoryUsageSkipsGaugeWhenLockIsPresent
entirely, as the Redis lock and Datadog gauge logic were removed.
Added Empty Selection Test:
Introduced
testEmptySelectionLogsAndReturnsFalse
to verify that processing an empty selection logs a debug message, skips batch manager operations (
generateName
,
scheduleWork
,
finishWork
), skips the stats reporter, and cleanly returns
false
.
Updated Existing Tests:
Modified
testRunUpdate
and
testRunDoUpdateButThrottled
to assert that the
$statsReporter->report()
method is called and to utilize the updated status manager mock.
Helper Method Refactoring
Helper Method Refactoring
Dynamic Status Manager Assertions:
Updated the
prepareStatusManager(int $invokeTimes = 0)
method to accept an integer. This allows tests to dynamically assert exactly how many times methods like
generateName
,
setUpdateTarget
,
scheduleWork
, and
finishWork
are invoked.
Removed Obsolete Helpers:
Deleted the
prepareLogger()...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
84026
|
2897
|
19
|
2026-05-28T11:18:53.373539+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967133373_m1.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"AI Chat settings","depth":3,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":3,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Main menu","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open mode picker, currently 3.1 Pro","depth":6,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
4333739136906508205
|
-3106538913866124061
|
typing_pause
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro...
|
84024
|
NULL
|
NULL
|
NULL
|
|
84025
|
2898
|
30
|
2026-05-28T11:18:52.928494+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967132928_m2.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.11402926,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.27055067,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.28172386,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.37988827,"width":0.09740692,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"bounds":{"left":0.0,"top":0.40143654,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.41260973,"width":0.08543883,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.43415803,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.44533122,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0,"top":0.4668795,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.47805268,"width":0.10106383,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"bounds":{"left":0.0028257978,"top":0.5047885,"width":0.036070477,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0028257978,"top":0.528332,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015957447,"top":0.5395052,"width":0.013297873,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.0028257978,"top":0.56105345,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"bounds":{"left":0.015957447,"top":0.57222664,"width":0.1271609,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.5937749,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
-2999881891330905920
|
-1952491857111026441
|
typing_pause
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket...
|
84023
|
NULL
|
NULL
|
NULL
|
|
84024
|
2897
|
18
|
2026-05-28T11:18:52.811014+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967132811_m1.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
-1860515063492607853
|
-3106536994015218461
|
typing_pause
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
84023
|
2898
|
29
|
2026-05-28T11:18:49.522952+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967129522_m2.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.11402926,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.27055067,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
4005828102058786328
|
-7727228562094562093
|
typing_pause
|
hybrid
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
rircroxcoltViewhsttonooonnsinePotLe.VindowHelp= github.com/~ Google GeminiPipelines - jiminny/appGemini 3.1 Pro ~* (JY-20613) Allow owner's role to tText relayDeleted object errAxUewredtines on New codJY-20963 fix deleted object impsJiminny\Exceptions(EmailActivityfrM Inbox (1,733) - lukas.kovalik@jiminioonre Reso ve php 81.15 ded8 JiminmPlatform Sorint 5.02 - Platform Te8 Jiminny7 (SRD-6881] (On demand) TransSona Strbramaal an at 27/05/2021O Illyana Netsova at 27/05/2026, 18Jy 20910 schedule parallel up: X— Now Tab3c503006111478686b8441263e32426fefdfbe6fe27c8271e2c3acbignore tests for now. Just focus on non test filesTd be nappy to review the implementation code, but the git dim you provided only contains changesto a single test file: UpdateProcessManagerTest.php.Because the actual source files (such as (UpdateProcessManager.php orReindexTargetStatsReporter.php ) are not included in the snippet, I cannot analyze them forpotential issues.If you provide the code or the diff for the non-test files, I will gladly review them for logic flaws,architectural risks, or pertormance concerns.I1 OpenJy 20910 schedule parallel uodate target processing 812 130All commits - | Vasil-Jiminny wants to merge 65 commits into naster from JY-20910-schedule-parallel-update-target-processingCFilter tec.V app/Traits/GracefullyStoppable.php C ÷~ & app~ fi Component/ESEntityTypeReindexer.phpReindexTargetStatsReporter,p...UpdateProcessManager.phpv Console~ #i Commands/ElasticsearchAsyncUpdateEsEntities.php•1AsvncUodateSupervisor.ohoDeleteEmailDocumentsCom…ReindexEntityTypes.php•1 RemoveGhostParticipantsCo.….ResetAsyncElasticSearchCo...Đ Kernel.php~ # Contracts/ESStopSignallnterface.php~ Ei TraitsP GracefullvStonoable.oho~ Ei tests/Unit/Component/ESEntityTypeReindexerTest.phpReindexTargetStatsReporterTes…UpdateProcessManagerTest.phpdie();public function pausel: voidstns-oshalPausecihneosthnllPanta = tmuessthseornuissaocsprintftHostnase ts pid is paused.gethostnane(),oelSvooouoocTunceion tesubel: vord11 (Sthis->shallPause)Sthis-schallPause = talse.sthis->orantvessaoeusprintf(hos hasoosressoscet6octa1e4loctsypid)REview PR, be very details and|lYor lim nou chate teho' uend to imnrmy our moddle Camialie 411t cao mata mttnkae co donbls chact" Yoir orhacy & CaminSummarize page00 в0.oubite tucetto0 sar Readvtostool: woralSthie-areadvToStoo & truedpublic function stopSignalReceived(string Snessage = **): void* :70 +7185 +Q< SOMOX 100%K3 8• Thu 28 May 14:18:490 2/15 viewedAwaiting approvalSubnitrevie °+44 -43 BB00 Viewedpublie function pauset): votad11 (1 Sthis->shallPause) (Sthis->shallPause = true;sthis->printMessage(sprintf(' --- Process $s PAUSED.', getaypid())):public function resune(): voidif (Sthis->shallPause) (Sthis->shallPause = false;Sthis->orintMessacelsorintt/'=e= Process fs RESIMED.". oetrvo1d0)))?puble function markShall5topl): voidSthis->shallStop = true;puslic function markleadylostopl); volSthise>readvToStoo = truelpublic function setMessage0nExit(?string Snessage = null): void...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
84022
|
2897
|
17
|
2026-05-28T11:18:47.330550+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967127330_m1.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
-2112793529402417778
|
4739293140786619618
|
typing_pause
|
hybrid
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
SlackFileEditViewGoHistoryWindowHelpDOCKERDOCKER (-zsh)2c55fe91ca4148a230e32eadocker_lamp_12026] No failed transcriptidocker_lamp_18? Stadocker_lamp_1205 Ddocker_lamp_1roc/1/fd/1'2>&1docker_lamp_12026ONEdocker_lamp_1 |Gracefully Stopping...Container docker-blackfContainer docker-mariadContainer kibanaStoppiContainer docker_lamp_1Container docker-jiminnContainer ngrok StoppinContainer docker-datadoContainer docker-datadoContainer docker-blackfContainer kibana StoppeContainer elasticsearchContainer docker-jiminnContainer elasticsearchmariadb-11 2026-0ownngrokt=2026pReq="{err: ‹nil>restarmariadb-12026-0ngrokt=2026on err=nilngrokt=2026f0743derr="reconnectinContainer docker_lamp_1Container ngrokError EContainer docker-mariadunexpected EOFerror during connect: Painers/ala97af7b5a28480What's next:Debug this Composelukas@Lukas-Kovaliks-MaV ALL VAULTS8My vaultExported%8All items* FavouritesBinV TYPESLoginCardIdentitySecure noteSSH keyFOLDERS+2FACSV Import 28.01.22LastPass Import 1.11.21NAS UsersSalesloftStarter KitNo folderCOLLECTIONSPersonal collectionMy vaultSendQ [URL_WITH_CREDENTIALS] mJ2STigExRjaUT^BoFy8NFEDOhttps://blog.whitelabeltechnologies....J2STigExRjaUT^BoFy8NFEDOhttps://www.rescuetime.com/log...XDLHx3m/Vangseyhttps://www.rescuetime.com/login?https://www.outsourcely.com/log..mLkl1230Shttps://www.outsourcely.com/login/Lkl1230Shttps://www.martinus.sk/login/?r..mLkl123Mhttps://www.martinus.sk/login/?redi..Lk/123Mhttps://www.jefit.com/login/m141122+HomeDMsActivityFilesLaterMore+ED→Jiminny ...# engineering# general# happy_birthday& infosec_internal_all# infra-changes#infrastructure_dev# jbu-team-info# jiminny-bg# platform-team# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of jimi...Direct messagesEo Vasil Vasilev •o Stoyan TomovLo lliyana Netseva&. Petko Kashinski®. Galya Dimitrovaa. Stefka Stoyanova* Todor Stamatov&. Steliyan Georgiev@ Vesg. Mira100% C8• Thu 28 May 14:18:46Describe what you are looking for# engineering8 246 0• MessagesP CanvasC FilesMore v+ledicated Host in AWS ConsoleFriday, May 22ndYes, that's expected behavicr with EC2 Mac Dedicated Hosts, and it's one of the most important"gotchas" in AWS Mac.What happenedTouteterro acitiohWe mehnenhThat reservation is now tied to your accourtAWS enforces a minimum allocation period (typically 24 hours)|3 replies Last reply 6 days agoSaturday, May 23rd ~Ves 5:46 PMHey team,PHP 8.5 release is live. After the holidays fetch thelatest dev docker image to make sure you have the8.5.5 runtime locally.HHH6Today ~Vasil Vasilev ®l 2:07 PMAction failed with error: SDK executionerror: Error: Claude Code returned an errorresult: API Error: 400 You have reached yourspecified API usage limits. You will regainaccess on 2026-06-01 at 00:00 UTC.I exhausted up all review tokensMessage #engineering...
|
84020
|
NULL
|
NULL
|
NULL
|
|
84021
|
2898
|
28
|
2026-05-28T11:18:47.211694+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967127211_m2.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.11402926,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.27055067,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.28172386,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.37988827,"width":0.09740692,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"bounds":{"left":0.0,"top":0.40143654,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.41260973,"width":0.08543883,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.43415803,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.44533122,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0,"top":0.4668795,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.47805268,"width":0.10106383,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"bounds":{"left":0.0028257978,"top":0.5047885,"width":0.036070477,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0028257978,"top":0.528332,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015957447,"top":0.5395052,"width":0.013297873,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.0028257978,"top":0.56105345,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"bounds":{"left":0.015957447,"top":0.57222664,"width":0.1271609,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.5937749,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.6049481,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.62649643,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.63766956,"width":0.12134308,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.6592179,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.6703911,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.69193935,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.70311254,"width":0.18201463,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.06732048,"top":0.69912213,"width":0.007978723,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.0028257978,"top":0.72625697,"width":0.07413564,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"bounds":{"left":0.0028257978,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"bounds":{"left":0.013796543,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"bounds":{"left":0.024933511,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"bounds":{"left":0.036070477,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"bounds":{"left":0.04720745,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"AI Chat settings","depth":3,"bounds":{"left":0.35854387,"top":0.055067837,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":3,"bounds":{"left":0.37051198,"top":0.055067837,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
426904441491657512
|
-3105408620207737629
|
typing_pause
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close...
|
84019
|
NULL
|
NULL
|
NULL
|
|
84020
|
2897
|
16
|
2026-05-28T11:18:46.317524+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967126317_m1.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:
Structural and Dependency Changes
Structural and Dependency Changes
Replaced Datadog:
Removed the
ChaseConey\LaravelDatadogHelper\Datadog
dependency and replaced it with
Jiminny\Component\ES\ReindexTargetStatsReporter
.
Added Constants and Properties:
Introduced a new
ENVIRONMENT
constant (set to
'testing'
) and a
$statsReporter
property to hold the mock for the new stats reporter.
Processor Instantiation:
Updated the
getProcessor()
method to inject the new
$statsReporter
mock into the
UpdateProcessManager
and utilize the
ENVIRONMENT
constant.
Test Case Modifications
Test Case Modifications
Removed Memory Logging Tests:
Deleted
testLogMemoryUsageEmitsGaugeWhenLockIsAbsent
and
testLogMemoryUsageSkipsGaugeWhenLockIsPresent
entirely, as the Redis lock and Datadog gauge logic were removed.
Added Empty Selection Test:
Introduced
testEmptySelectionLogsAndReturnsFalse
to verify that processing an empty selection logs a debug message, skips batch manager operations (
generateName
,
scheduleWork
,
finishWork
), skips the stats reporter, and cleanly returns
false
.
Updated Existing Tests:
Modified
testRunUpdate
and
testRunDoUpdateButThrottled
to assert that the
$statsReporter->report()
method is called and to utilize the updated status manager mock.
Helper Method Refactoring
Helper Method Refactoring
Dynamic Status Manager Assertions:
Updated the
prepareStatusManager(int $invokeTimes = 0)
method to accept an integer. This allows tests to dynamically assert exactly how many times methods like
generateName
,
setUpdateTarget
,
scheduleWork
, and
finishWork
are invoked....
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"AI Chat settings","depth":3,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":3,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Main menu","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open mode picker, currently 3.1 Pro","depth":6,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Gemini","depth":13,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"3.1 Pro","depth":11,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Chat","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open menu for conversation actions.","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Conversation with Gemini","depth":7,"on_screen":true,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Conversation with Gemini","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":13,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"You said","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.","depth":15,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Expand","depth":13,"on_screen":false,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Copy prompt","depth":12,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Gemini said","depth":12,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Gemini said","depth":13,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Here is a summary of the changes in the provided git diff for","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"UpdateProcessManagerTest.php","depth":17,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":":","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Structural and Dependency Changes","depth":15,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Structural and Dependency Changes","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Replaced Datadog:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Removed the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ChaseConey\\LaravelDatadogHelper\\Datadog","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"dependency and replaced it with","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Jiminny\\Component\\ES\\ReindexTargetStatsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":".","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Added Constants and Properties:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Introduced a new","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ENVIRONMENT","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"constant (set to","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"'testing'","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":") and a","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"$statsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"property to hold the mock for the new stats reporter.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Processor Instantiation:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Updated the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"getProcessor()","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"method to inject the new","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"$statsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"mock into the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"UpdateProcessManager","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"and utilize the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ENVIRONMENT","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"constant.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Test Case Modifications","depth":15,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Test Case Modifications","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Removed Memory Logging Tests:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Deleted","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testLogMemoryUsageEmitsGaugeWhenLockIsAbsent","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"and","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testLogMemoryUsageSkipsGaugeWhenLockIsPresent","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"entirely, as the Redis lock and Datadog gauge logic were removed.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Added Empty Selection Test:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Introduced","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testEmptySelectionLogsAndReturnsFalse","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"to verify that processing an empty selection logs a debug message, skips batch manager operations (","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"generateName","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":",","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"scheduleWork","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":",","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"finishWork","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"), skips the stats reporter, and cleanly returns","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"false","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":".","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Updated Existing Tests:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Modified","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testRunUpdate","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"and","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"testRunDoUpdateButThrottled","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"to assert that the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"$statsReporter->report()","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"method is called and to utilize the updated status manager mock.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Helper Method Refactoring","depth":15,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Helper Method Refactoring","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Dynamic Status Manager Assertions:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Updated the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"prepareStatusManager(int $invokeTimes = 0)","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"method to accept an integer. This allows tests to dynamically assert exactly how many times methods like","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"generateName","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":",","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"setUpdateTarget","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":",","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"scheduleWork","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":", and","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"finishWork","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"are invoked.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
4016020592673904087
|
-3403141220449881980
|
typing_pause
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:
Structural and Dependency Changes
Structural and Dependency Changes
Replaced Datadog:
Removed the
ChaseConey\LaravelDatadogHelper\Datadog
dependency and replaced it with
Jiminny\Component\ES\ReindexTargetStatsReporter
.
Added Constants and Properties:
Introduced a new
ENVIRONMENT
constant (set to
'testing'
) and a
$statsReporter
property to hold the mock for the new stats reporter.
Processor Instantiation:
Updated the
getProcessor()
method to inject the new
$statsReporter
mock into the
UpdateProcessManager
and utilize the
ENVIRONMENT
constant.
Test Case Modifications
Test Case Modifications
Removed Memory Logging Tests:
Deleted
testLogMemoryUsageEmitsGaugeWhenLockIsAbsent
and
testLogMemoryUsageSkipsGaugeWhenLockIsPresent
entirely, as the Redis lock and Datadog gauge logic were removed.
Added Empty Selection Test:
Introduced
testEmptySelectionLogsAndReturnsFalse
to verify that processing an empty selection logs a debug message, skips batch manager operations (
generateName
,
scheduleWork
,
finishWork
), skips the stats reporter, and cleanly returns
false
.
Updated Existing Tests:
Modified
testRunUpdate
and
testRunDoUpdateButThrottled
to assert that the
$statsReporter->report()
method is called and to utilize the updated status manager mock.
Helper Method Refactoring
Helper Method Refactoring
Dynamic Status Manager Assertions:
Updated the
prepareStatusManager(int $invokeTimes = 0)
method to accept an integer. This allows tests to dynamically assert exactly how many times methods like
generateName
,
setUpdateTarget
,
scheduleWork
, and
finishWork
are invoked....
|
NULL
|
NULL
|
NULL
|
NULL
|
|
84019
|
2898
|
27
|
2026-05-28T11:18:46.087725+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967126087_m2.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:
Structural and Dependency Changes
Structural and Dependency Changes
Replaced Datadog:
Removed the
ChaseConey\LaravelDatadogHelper\Datadog
dependency and replaced it with
Jiminny\Component\ES\ReindexTargetStatsReporter
.
Added Constants and Properties:
Introduced a new
ENVIRONMENT
constant (set to...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.11402926,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.27055067,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.28172386,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.37988827,"width":0.09740692,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"bounds":{"left":0.0,"top":0.40143654,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.41260973,"width":0.08543883,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.43415803,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.44533122,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0,"top":0.4668795,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.47805268,"width":0.10106383,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"bounds":{"left":0.0028257978,"top":0.5047885,"width":0.036070477,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0028257978,"top":0.528332,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015957447,"top":0.5395052,"width":0.013297873,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.0028257978,"top":0.56105345,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"bounds":{"left":0.015957447,"top":0.57222664,"width":0.1271609,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.5937749,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.6049481,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.62649643,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.63766956,"width":0.12134308,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.6592179,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.6703911,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.69193935,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.70311254,"width":0.18201463,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.06732048,"top":0.69912213,"width":0.007978723,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.0028257978,"top":0.72625697,"width":0.07413564,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"bounds":{"left":0.0028257978,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"bounds":{"left":0.013796543,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"bounds":{"left":0.024933511,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"bounds":{"left":0.036070477,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"bounds":{"left":0.04720745,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"AI Chat settings","depth":3,"bounds":{"left":0.35854387,"top":0.055067837,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":3,"bounds":{"left":0.37051198,"top":0.055067837,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Main menu","depth":5,"bounds":{"left":0.08228058,"top":0.09736632,"width":0.015957447,"height":0.03830806},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open mode picker, currently 3.1 Pro","depth":6,"bounds":{"left":0.09823803,"top":0.10694334,"width":0.047539894,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Gemini","depth":13,"bounds":{"left":0.1022274,"top":0.10853951,"width":0.017121011,"height":0.016360734},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"3.1 Pro","depth":11,"bounds":{"left":0.12084442,"top":0.10853951,"width":0.013796543,"height":0.015961692},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Chat","depth":5,"bounds":{"left":0.35854387,"top":0.10215483,"width":0.011968086,"height":0.028731046},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open menu for conversation actions.","depth":5,"bounds":{"left":0.37051198,"top":0.10215483,"width":0.011968086,"height":0.028731046},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Conversation with Gemini","depth":7,"bounds":{"left":0.079288565,"top":0.14445332,"width":0.0003324468,"height":0.0007980846},"on_screen":true,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Conversation with Gemini","depth":8,"bounds":{"left":0.079288565,"top":0.14684756,"width":0.1200133,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":13,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"You said","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.","depth":15,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Expand","depth":13,"on_screen":false,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Copy prompt","depth":12,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Gemini said","depth":12,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Gemini said","depth":13,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Here is a summary of the changes in the provided git diff for","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"UpdateProcessManagerTest.php","depth":17,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":":","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Structural and Dependency Changes","depth":15,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Structural and Dependency Changes","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Replaced Datadog:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Removed the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ChaseConey\\LaravelDatadogHelper\\Datadog","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"dependency and replaced it with","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Jiminny\\Component\\ES\\ReindexTargetStatsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":".","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Added Constants and Properties:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Introduced a new","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ENVIRONMENT","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"constant (set to","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
2724782134424365835
|
-3259026032374026108
|
typing_pause
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:
Structural and Dependency Changes
Structural and Dependency Changes
Replaced Datadog:
Removed the
ChaseConey\LaravelDatadogHelper\Datadog
dependency and replaced it with
Jiminny\Component\ES\ReindexTargetStatsReporter
.
Added Constants and Properties:
Introduced a new
ENVIRONMENT
constant (set to...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
84018
|
2898
|
26
|
2026-05-28T11:18:45.249018+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967125249_m2.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:
Structural and Dependency Changes
Structural and Dependency Changes
Replaced Datadog:
Removed the
ChaseConey\LaravelDatadogHelper\Datadog
dependency and replaced it with
Jiminny\Component\ES\ReindexTargetStatsReporter
.
Added Constants and Properties:
Introduced a new
ENVIRONMENT
constant (set to
'testing'
) and a
$statsReporter
property to hold the mock for the new stats reporter.
Processor Instantiation:
Updated the
getProcessor()
method to inject the new
$statsReporter
mock into the
UpdateProcessManager
and utilize the...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.11402926,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.27055067,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.28172386,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.37988827,"width":0.09740692,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"bounds":{"left":0.0,"top":0.40143654,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.41260973,"width":0.08543883,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.43415803,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.44533122,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0,"top":0.4668795,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.47805268,"width":0.10106383,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"bounds":{"left":0.0028257978,"top":0.5047885,"width":0.036070477,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0028257978,"top":0.528332,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015957447,"top":0.5395052,"width":0.013297873,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.0028257978,"top":0.56105345,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"bounds":{"left":0.015957447,"top":0.57222664,"width":0.1271609,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.5937749,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.6049481,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.62649643,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.63766956,"width":0.12134308,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.6592179,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.6703911,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.69193935,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.70311254,"width":0.18201463,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.06732048,"top":0.69912213,"width":0.007978723,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.0028257978,"top":0.72625697,"width":0.07413564,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"bounds":{"left":0.0028257978,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"bounds":{"left":0.013796543,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"bounds":{"left":0.024933511,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"bounds":{"left":0.036070477,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"bounds":{"left":0.04720745,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"AI Chat settings","depth":3,"bounds":{"left":0.35854387,"top":0.055067837,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":3,"bounds":{"left":0.37051198,"top":0.055067837,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Main menu","depth":5,"bounds":{"left":0.08228058,"top":0.09736632,"width":0.015957447,"height":0.03830806},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open mode picker, currently 3.1 Pro","depth":6,"bounds":{"left":0.09823803,"top":0.10694334,"width":0.047539894,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Gemini","depth":13,"bounds":{"left":0.1022274,"top":0.10853951,"width":0.017121011,"height":0.016360734},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"3.1 Pro","depth":11,"bounds":{"left":0.12084442,"top":0.10853951,"width":0.013796543,"height":0.015961692},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Chat","depth":5,"bounds":{"left":0.35854387,"top":0.10215483,"width":0.011968086,"height":0.028731046},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open menu for conversation actions.","depth":5,"bounds":{"left":0.37051198,"top":0.10215483,"width":0.011968086,"height":0.028731046},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Conversation with Gemini","depth":7,"bounds":{"left":0.079288565,"top":0.14445332,"width":0.0003324468,"height":0.0007980846},"on_screen":true,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Conversation with Gemini","depth":8,"bounds":{"left":0.079288565,"top":0.14684756,"width":0.1200133,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":13,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"You said","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.","depth":15,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Expand","depth":13,"on_screen":false,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Copy prompt","depth":12,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Gemini said","depth":12,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Gemini said","depth":13,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Here is a summary of the changes in the provided git diff for","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"UpdateProcessManagerTest.php","depth":17,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":":","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Structural and Dependency Changes","depth":15,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Structural and Dependency Changes","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Replaced Datadog:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Removed the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ChaseConey\\LaravelDatadogHelper\\Datadog","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"dependency and replaced it with","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Jiminny\\Component\\ES\\ReindexTargetStatsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":".","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Added Constants and Properties:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Introduced a new","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"ENVIRONMENT","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"constant (set to","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"'testing'","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":") and a","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"$statsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"property to hold the mock for the new stats reporter.","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Processor Instantiation:","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Updated the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"getProcessor()","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"method to inject the new","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"$statsReporter","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"mock into the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"UpdateProcessManager","depth":19,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"and utilize the","depth":18,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
-3267527678470332118
|
-3259026032374026108
|
typing_pause
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:
Structural and Dependency Changes
Structural and Dependency Changes
Replaced Datadog:
Removed the
ChaseConey\LaravelDatadogHelper\Datadog
dependency and replaced it with
Jiminny\Component\ES\ReindexTargetStatsReporter
.
Added Constants and Properties:
Introduced a new
ENVIRONMENT
constant (set to
'testing'
) and a
$statsReporter
property to hold the mock for the new stats reporter.
Processor Instantiation:
Updated the
getProcessor()
method to inject the new
$statsReporter
mock into the
UpdateProcessManager
and utilize the...
|
84016
|
NULL
|
NULL
|
NULL
|
|
84017
|
2897
|
15
|
2026-05-28T11:18:45.112258+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967125112_m1.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy....
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"AI Chat settings","depth":3,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":3,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Main menu","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open mode picker, currently 3.1 Pro","depth":6,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Gemini","depth":13,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"3.1 Pro","depth":11,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Chat","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open menu for conversation actions.","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Conversation with Gemini","depth":7,"on_screen":true,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Conversation with Gemini","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":13,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"}]...
|
1717921840857720572
|
-3393641439985897308
|
typing_pause
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy....
|
84015
|
NULL
|
NULL
|
NULL
|
|
84016
|
2898
|
25
|
2026-05-28T11:18:40.643322+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967120643_m2.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.11402926,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.27055067,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.28172386,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.37988827,"width":0.09740692,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"bounds":{"left":0.0,"top":0.40143654,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.41260973,"width":0.08543883,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.43415803,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.44533122,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0,"top":0.4668795,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.47805268,"width":0.10106383,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"bounds":{"left":0.0028257978,"top":0.5047885,"width":0.036070477,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0028257978,"top":0.528332,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
-6704020844598827239
|
-844606344482983709
|
typing_pause
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
84015
|
2897
|
14
|
2026-05-28T11:18:40.285893+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967120285_m1.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
-7596359022631232114
|
-3105415491081669405
|
typing_pause
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
84014
|
2898
|
24
|
2026-05-28T11:18:39.626607+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967119626_m2.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.11402926,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.27055067,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.28172386,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
1451921993773326004
|
-5736636977105734973
|
typing_pause
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail...
|
84012
|
NULL
|
NULL
|
NULL
|
|
84013
|
2897
|
13
|
2026-05-28T11:18:35.830482+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967115830_m1.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
-2112793529402417778
|
4739293140786619618
|
click
|
hybrid
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
SlackFileEditViewGoHistoryWindowHelpDOCKERDOCKER (-zsh)2c55fe91ca4148a230e32eadocker_lamp_12026] No failed transcriptidocker_lamp_18? Stadocker_lamp_1205 Ddocker_lamp_1roc/1/fd/1'2>&1docker_lamp_12026ONEdocker_lamp_1 |Gracefully Stopping...Container docker-blackfContainer docker-mariadContainer kibanaStoppiContainer docker_lamp_1Container docker-jiminnContainer ngrok StoppinContainer docker-datadoContainer docker-datadoContainer docker-blackfContainer kibana StoppeContainer elasticsearchContainer docker-jiminnContainer elasticsearchmariadb-11 2026-0ownngrokt=2026pReq="{err: ‹nil>restarmariadb-12026-0ngrokt=2026on err=nilngrokt=2026f0743derr="reconnectinContainer docker_lamp_1Container ngrokError EContainer docker-mariadunexpected EOFerror during connect: Painers/ala97af7b5a28480What's next:Debug this Composelukas@Lukas-Kovaliks-MaV ALL VAULTS8My vaultExported%8All items* FavouritesBinV TYPESLoginCardIdentitySecure noteSSH keyFOLDERS+2FACSV Import 28.01.22LastPass Import 1.11.21NAS UsersSalesloftStarter KitNo folderCOLLECTIONSPersonal collectionMy vaultSendQ [URL_WITH_CREDENTIALS] mJ2STigExRjaUT^BoFy8NFEDOhttps://blog.whitelabeltechnologies....J2STigExRjaUT^BoFy8NFEDOhttps://www.rescuetime.com/log...XDLHx3m/Vangseyhttps://www.rescuetime.com/login?https://www.outsourcely.com/log..mLkl1230Shttps://www.outsourcely.com/login/Lkl1230Shttps://www.martinus.sk/login/?r..mLkl123Mhttps://www.martinus.sk/login/?redi..Lk/123Mhttps://www.jefit.com/login/m141122+HomeDMsActivityFilesLaterMore+ED→Jiminny ...# engineering# general# happy_birthday& infosec_internal_all# infra-changes#infrastructure_dev# jbu-team-info# jiminny-bg# platform-team# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of jimi...Direct messageso Vasil Vasilev 0o Stoyan TomovLo lliyana Netseva&. Petko Kashinski®. Galya Dimitrovaa. Stefka Stoyanova* Todor Stamatov&. Steliyan Georgiev. Vesg. Mira100% C8• Thu 28 May 14:18:35Describe what you are looking for# engineering8 246 0• MessagesP CanvasC FilesMore v+ledicated Host in AWS ConsoleFriday, May 22ndYes, that's expected behavicr with EC2 Mac Dedicated Hosts, and it's one of the most important"gotchas" in AWS Mac.What happenedTouteterro acitiohWe mehnenhThat reservation is now tied to your accourtAWS enforces a minimum allocation period (typically 24 hours)|3 replies Last reply 6 days agoSaturday, May 23rd ~Ves 5:46 PMHey team,PHP 8.5 release is live. After the holidays fetch thelatest dev docker image to make sure you have the8.5.5 runtime locally.HHH6Today ~Vasil Vasilev ®l 2:07 PMAction failed with error: SDK executionerror: Error: Claude Code returned an errorresult: API Error: 400 You have reached yourspecified API usage limits. You will regainaccess on 2026-06-01 at 00:00 UTC.I exhausted up all review tokensMessage #engineering...
|
84007
|
NULL
|
NULL
|
NULL
|
|
84012
|
2898
|
23
|
2026-05-28T11:18:38.597397+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967118597_m2.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.11402926,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.27055067,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.28172386,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
3479347533214238294
|
-5709614829585959209
|
typing_pause
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
84011
|
2898
|
22
|
2026-05-28T11:18:35.172021+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967115172_m2.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
rircroxViewhsttonooonnsinePotLe.WindowHelp= github rircroxViewhsttonooonnsinePotLe.WindowHelp= github.com/~ Google GeminiPipelines - jiminny/appGemini 3.1 Pro ~* (JY-20613) Allow owner's role to tText relayDeleted object errxUewredtines on New codJY-20963 fix deleted object impsJiminny\Exceptions(EmailActivityfrM Inbox (1,733) - lukas.kovalik@jiminioonre Reso ve php 81.15 ded8 Jiminm,Platform Sorint 5.02 - Platform Te8 Jiminny7 (SRD-6881] (On demand) TransSona Strbramaal an at 27/05/2021O Illyana Netsova at 27/05/2026, 18Jy 20910 schedule parallel upc— Now Tab3c503006111478686b8441263e32426fefdfbe6fe27c8271e2c3acbignore tests for now. Just focus on non test filesTd be nappy to review the implementation code, but the git dim you provided only contains changesto a single test file: UpdateProcessManagerTest.php.Because the actual source files (such as (UpdateProcessManager.php orReindexTargetStatsReporter.php ) are not included in the snippet, I cannot analyze them forpotential issues.If you provide the code or the diff for the non-test files, I will gladly review them for logic flaws,architectural risks, or pertormance concerns.I1 OpenJy 20910 schedule parallel uodate target processing 812 130All commits - | Vasil-Jiminny wants to merge 65 commits into naster from JY-20910-schedule-parallel-update-target-processingCFilter tec.V app/Traits/GracefullyStoppable.php C ÷~ & app~ Ei Component/ESEntityTypeReindexer.phpReindexTargetStatsReporter,p...UpdateProcessManager.phpv Console~ #i Commands/ElasticsearchAsyncUpdateEsEntities.php•1AsvncUodateSupervisor.ohoDeleteEmailDocumentsCom…ReindexEntityTypes.php•1 RemoveGhostParticipantsCo.….ResetAsyncElasticSearchCo...Đ Kernel.php~ # Contracts/ESStopSignallnterface.php~ Ei TraitsP GracefullvStonoable.oho~ Ei tests/Unit/Component/ESEntityTypeReindexerTest.phpReindexTargetStatsReporterTes.UpdateProcessManagerTest.phpdie();public function pausel: voidstns-oshalPausecihneosthnllPanta = tmuessthseornuissaocsprintftHostnase "s pid is paused.gethostnane(),oelCvooouoocTunceion tesubel: vord11 (Sthis->shallPause)Sthis-schallPause = talse.sthis->orantvessaoeusprintf(hos hasoosressoscet6octa1e4loctsypid)ASX GeminilYor lim nou chate teho' uend to imnrmy our moddle Camialie 411t can mata mttnkae co donbls chact" Yoir orhacy & CaminSummarize page00 в0.oubite tucetto0 sar Readvtostool: woralSthie-areadvToStoo & truedpublic function stopSignalReceived(string Snessage = **): void* :6670 +7185 +Q< SOMOX 100%K3 8• Thu 28 May 14:18:340 2/15 viewedAnaiuns approvalbmit review -+44 -43 BB00 Viewedpublie function pauset): votad11 (1 Sthis->shallPause) (Sthis->shallPause = true;sthis->printMessage(sprintf(' --- Process $s PAUSED.', getaypid())):public function resune(): voidif (Sthis->shallPause) (Sthis->shallPause = false;Sthis->orintMessacelsorintt/'=e= Process fs RESIMED.". oetrvo1d0)))?publie function markShall5topt): vosdSthis->shallStop = true;puslic function markleadylostopl); volSthise>readvToStoo = truedpublic function setMessage0nExit(?string Snessage = null): void...
|
NULL
|
5181250198143241640
|
NULL
|
visual_change
|
ocr
|
NULL
|
rircroxViewhsttonooonnsinePotLe.WindowHelp= github rircroxViewhsttonooonnsinePotLe.WindowHelp= github.com/~ Google GeminiPipelines - jiminny/appGemini 3.1 Pro ~* (JY-20613) Allow owner's role to tText relayDeleted object errxUewredtines on New codJY-20963 fix deleted object impsJiminny\Exceptions(EmailActivityfrM Inbox (1,733) - lukas.kovalik@jiminioonre Reso ve php 81.15 ded8 Jiminm,Platform Sorint 5.02 - Platform Te8 Jiminny7 (SRD-6881] (On demand) TransSona Strbramaal an at 27/05/2021O Illyana Netsova at 27/05/2026, 18Jy 20910 schedule parallel upc— Now Tab3c503006111478686b8441263e32426fefdfbe6fe27c8271e2c3acbignore tests for now. Just focus on non test filesTd be nappy to review the implementation code, but the git dim you provided only contains changesto a single test file: UpdateProcessManagerTest.php.Because the actual source files (such as (UpdateProcessManager.php orReindexTargetStatsReporter.php ) are not included in the snippet, I cannot analyze them forpotential issues.If you provide the code or the diff for the non-test files, I will gladly review them for logic flaws,architectural risks, or pertormance concerns.I1 OpenJy 20910 schedule parallel uodate target processing 812 130All commits - | Vasil-Jiminny wants to merge 65 commits into naster from JY-20910-schedule-parallel-update-target-processingCFilter tec.V app/Traits/GracefullyStoppable.php C ÷~ & app~ Ei Component/ESEntityTypeReindexer.phpReindexTargetStatsReporter,p...UpdateProcessManager.phpv Console~ #i Commands/ElasticsearchAsyncUpdateEsEntities.php•1AsvncUodateSupervisor.ohoDeleteEmailDocumentsCom…ReindexEntityTypes.php•1 RemoveGhostParticipantsCo.….ResetAsyncElasticSearchCo...Đ Kernel.php~ # Contracts/ESStopSignallnterface.php~ Ei TraitsP GracefullvStonoable.oho~ Ei tests/Unit/Component/ESEntityTypeReindexerTest.phpReindexTargetStatsReporterTes.UpdateProcessManagerTest.phpdie();public function pausel: voidstns-oshalPausecihneosthnllPanta = tmuessthseornuissaocsprintftHostnase "s pid is paused.gethostnane(),oelCvooouoocTunceion tesubel: vord11 (Sthis->shallPause)Sthis-schallPause = talse.sthis->orantvessaoeusprintf(hos hasoosressoscet6octa1e4loctsypid)ASX GeminilYor lim nou chate teho' uend to imnrmy our moddle Camialie 411t can mata mttnkae co donbls chact" Yoir orhacy & CaminSummarize page00 в0.oubite tucetto0 sar Readvtostool: woralSthie-areadvToStoo & truedpublic function stopSignalReceived(string Snessage = **): void* :6670 +7185 +Q< SOMOX 100%K3 8• Thu 28 May 14:18:340 2/15 viewedAnaiuns approvalbmit review -+44 -43 BB00 Viewedpublie function pauset): votad11 (1 Sthis->shallPause) (Sthis->shallPause = true;sthis->printMessage(sprintf(' --- Process $s PAUSED.', getaypid())):public function resune(): voidif (Sthis->shallPause) (Sthis->shallPause = false;Sthis->orintMessacelsorintt/'=e= Process fs RESIMED.". oetrvo1d0)))?publie function markShall5topt): vosdSthis->shallStop = true;puslic function markleadylostopl); volSthise>readvToStoo = truedpublic function setMessage0nExit(?string Snessage = null): void...
|
84010
|
NULL
|
NULL
|
NULL
|
|
84010
|
2898
|
21
|
2026-05-28T11:18:31.916211+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967111916_m2.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Uncovered Lines on New Code - app in Jiminny SonarQube Cloud","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.11402926,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.27055067,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.28172386,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,733) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.37988827,"width":0.09740692,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"bounds":{"left":0.0,"top":0.40143654,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.41260973,"width":0.08543883,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.43415803,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.44533122,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0,"top":0.4668795,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.47805268,"width":0.10106383,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"bounds":{"left":0.0028257978,"top":0.5047885,"width":0.036070477,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0028257978,"top":0.528332,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015957447,"top":0.5395052,"width":0.013297873,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.0028257978,"top":0.56105345,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"bounds":{"left":0.015957447,"top":0.57222664,"width":0.1271609,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.5937749,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.6049481,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.62649643,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.63766956,"width":0.12134308,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.6592179,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.6703911,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.69193935,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.70311254,"width":0.18201463,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.06732048,"top":0.69912213,"width":0.007978723,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.0028257978,"top":0.72625697,"width":0.07413564,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"bounds":{"left":0.0028257978,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Close Google Gemini (⌃X)","depth":6,"bounds":{"left":0.013796543,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"bounds":{"left":0.024933511,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"bounds":{"left":0.036070477,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"bounds":{"left":0.04720745,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"AI Chat settings","depth":3,"bounds":{"left":0.35854387,"top":0.055067837,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Close","depth":3,"bounds":{"left":0.37051198,"top":0.055067837,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Main menu","depth":5,"bounds":{"left":0.08228058,"top":0.09736632,"width":0.015957447,"height":0.03830806},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open mode picker, currently 3.1 Pro","depth":6,"bounds":{"left":0.09823803,"top":0.10694334,"width":0.047539894,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Gemini","depth":13,"bounds":{"left":0.1022274,"top":0.10853951,"width":0.017121011,"height":0.016360734},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"3.1 Pro","depth":11,"bounds":{"left":0.12084442,"top":0.10853951,"width":0.013796543,"height":0.015961692},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Chat","depth":5,"bounds":{"left":0.35854387,"top":0.10215483,"width":0.011968086,"height":0.028731046},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open menu for conversation actions.","depth":5,"bounds":{"left":0.37051198,"top":0.10215483,"width":0.011968086,"height":0.028731046},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Conversation with Gemini","depth":7,"bounds":{"left":0.079288565,"top":0.14445332,"width":0.0003324468,"height":0.0007980846},"on_screen":true,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Conversation with Gemini","depth":8,"bounds":{"left":0.079288565,"top":0.14684756,"width":0.1200133,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":13,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"You said","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\\Unit\\Component\\ES;5namespace Tests\\Unit\\Component\\ES;667-use ChaseConey\\LaravelDatadogHelper\\Datadog;8use Elastica\\Index;7use Elastica\\Index;9use Illuminate\\Support\\Facades\\App;8use Illuminate\\Support\\Facades\\App;10use Illuminate\\Support\\Facades\\Log;9use Illuminate\\Support\\Facades\\Log;@@ -20,6 +19,7 @@20use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;19use Jiminny\\Component\\ES\\Processor\\TargetEntitiesSelector;21use Jiminny\\Component\\ES\\Processor\\UpdateTarget;20use Jiminny\\Component\\ES\\Processor\\UpdateTarget;22use Jiminny\\Component\\ES\\QueuePriorityEnum;21use Jiminny\\Component\\ES\\QueuePriorityEnum;22+use Jiminny\\Component\\ES\\ReindexTargetStatsReporter;23use Jiminny\\Component\\ES\\UpdateProcessManager;23use Jiminny\\Component\\ES\\UpdateProcessManager;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;24use Jiminny\\Contracts\\ES\\UpdateTargetEnum;25use PHPUnit\\Framework\\Attributes\\CoversClass;25use PHPUnit\\Framework\\Attributes\\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \\Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.","depth":15,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","depth":15,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Expand","depth":13,"on_screen":false,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Copy prompt","depth":12,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Gemini said","depth":12,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Gemini said","depth":13,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Here is a summary of the changes in the provided git diff for","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"UpdateProcessManagerTest.php","depth":17,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":":","depth":16,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
4697318989288948007
|
-3259026032374026108
|
visual_change
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
Uncovered Lines on New Code - app in Jiminny SonarQube Cloud
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,733) - [EMAIL] - Jiminny Mail
Inbox (1,733) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app
Close tab
New Tab
Customize sidebar
Close Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
AI Chat settings
Close
Main menu
Open mode picker, currently 3.1 Pro
Gemini
3.1 Pro
New Chat
Open menu for conversation actions.
Conversation with Gemini
Conversation with Gemini
You said I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected. Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
You said
I’m on page “<tabTitle>Jy 20910 schedule parallel update target processin</tabTitle>” with “<selection>@@ -4,7 +4,6 @@445namespace Tests\Unit\Component\ES;5namespace Tests\Unit\Component\ES;667-use ChaseConey\LaravelDatadogHelper\Datadog;8use Elastica\Index;7use Elastica\Index;9use Illuminate\Support\Facades\App;8use Illuminate\Support\Facades\App;10use Illuminate\Support\Facades\Log;9use Illuminate\Support\Facades\Log;@@ -20,6 +19,7 @@20use Jiminny\Component\ES\Processor\TargetEntitiesSelector;19use Jiminny\Component\ES\Processor\TargetEntitiesSelector;21use Jiminny\Component\ES\Processor\UpdateTarget;20use Jiminny\Component\ES\Processor\UpdateTarget;22use Jiminny\Component\ES\QueuePriorityEnum;21use Jiminny\Component\ES\QueuePriorityEnum;22+use Jiminny\Component\ES\ReindexTargetStatsReporter;23use Jiminny\Component\ES\UpdateProcessManager;23use Jiminny\Component\ES\UpdateProcessManager;24use Jiminny\Contracts\ES\UpdateTargetEnum;24use Jiminny\Contracts\ES\UpdateTargetEnum;25use PHPUnit\Framework\Attributes\CoversClass;25use PHPUnit\Framework\Attributes\CoversClass;@@ -31,6 +31,7 @@ class UpdateProcessManagerTest extends TestCase31{31{32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';32private const string BATCH_NAME = '9440de7a-1c0f-4541-a235-592f2117bb20';33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;33private const string UPDATE_TARGET = UpdateTarget::ACTIVITY;34+private const string ENVIRONMENT = 'testing';343535private array $normalPriority = [];36private array $normalPriority = [];36private array $highPriority = [];37private array $highPriority = [];@@ -40,6 +41,7 @@ class UpdateProcessManagerTest extends TestCase40private ?SimpleCollection $documentsToUpdate = null;41private ?SimpleCollection $documentsToUpdate = null;414242private BatchStatusManager|MockObject|null $batchStatusManager = null;43private BatchStatusManager|MockObject|null $batchStatusManager = null;44+private ReindexTargetStatsReporter|MockObject|null $statsReporter = null;43private Index|MockObject|null $targetIndex = null;45private Index|MockObject|null $targetIndex = null;444645private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;47private string|UpdateTargetEnum $updateTargetEntity = UpdateTarget::ACTIVITY;@@ -68,8 +70,13 @@ protected function setUp(): void68array_diff($allEntities, $deleteIds)70array_diff($allEntities, $deleteIds)69 );71 );707271-$this->prepareStatusManager();73+$this->statsReporter = $this->createMock(ReindexTargetStatsReporter::class);72-$this->prepareLogger();74+$this->statsReporter->expects($this->once())75+ ->method('setEnvironment')76+ ->with(self::ENVIRONMENT);77+$this->statsReporter->expects($this->once())78+ ->method('setUpdateTarget')79+ ->with(self::UPDATE_TARGET);73 }80 }748175/**82/**@@ -81,76 +88,75 @@ public function testRunUpdate(): void81// Also test that the trait works with entities and strings alike88// Also test that the trait works with entities and strings alike82$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;89$this->updateTargetEntity = UpdateTargetEnum::ACTIVITY;839084-$this->silenceDatadogAndRedisLock();91+ Log::shouldReceive('info')->withAnyArgs();92+ Log::shouldReceive('debug')->withAnyArgs();93+94+$this->statsReporter->expects($this->once())->method('report');95+96+$this->prepareStatusManager(1);859786$processor = $this->getProcessor();98$processor = $this->getProcessor();879988// There are exactly 250 chunks100// There are exactly 250 chunks89$this->assertTrue($processor->doUpdateEntitiesChunk());101$this->assertTrue($processor->doUpdateEntitiesChunk());102+90// But the second execution is on empty set103// But the second execution is on empty set91$this->assertFalse($processor->doUpdateEntitiesChunk());104$this->assertFalse($processor->doUpdateEntitiesChunk());92 }105 }9310694-/**107+public function testEmptySelectionLogsAndReturnsFalse(): void95- * When no Redis lock exists, logMemoryUsage should set the lock and emit a Datadog gauge96- * with the correct stat name, sample rate, and environment/type tags.97- */98-public function testLogMemoryUsageEmitsGaugeWhenLockIsAbsent(): void99 {108 {100-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);109+$batchStatusManager = $this->createMock(BatchStatusManager::class);101-110+$batchStatusManager->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);102- Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(null);111+$batchStatusManager->expects($this->never())->method('generateName');103- Redis::shouldReceive('set')->once()->with($gaugeLockKey, true);112+$batchStatusManager->expects($this->never())->method('scheduleWork');104- Redis::shouldReceive('expire')->once()->with($gaugeLockKey, 60);113+$batchStatusManager->expects($this->never())->method('finishWork');105-106- Datadog::shouldReceive('increment')->once()->withAnyArgs();107- Datadog::shouldReceive('gauge')108- ->once()109- ->with(110-'jiminny.reindex-memory-usage',111- \Mockery::type('int'),112-1,113- ['environment' => 'staging', 'type' => self::UPDATE_TARGET]114- );115-116-$processor = $this->getProcessor();117-$processor->setEnvironment('staging');118114119-$processor->doUpdateEntitiesChunk();115+$emptySelection = $this->createMock(SelectionList::class);120-}116+ $emptySelection->expects($this->once())->method('isEmpty')->willReturn(true);121117122-/**118+$entitySelector = $this->createMock(TargetEntitiesSelector::class);123- * When a Redis lock already exists, logMemoryUsage should return early119+$entitySelector->expects($this->once())->method('setUpdateTarget')->with(self::UPDATE_TARGET);124- * and not emit a Datadog gauge.120+$entitySelector->expects($this->once())->method('setBatchStatusManager')->with($batchStatusManager);125- */121+$entitySelector->expects($this->once())->method('select')->willReturn($emptySelection);126-public function testLogMemoryUsageSkipsGaugeWhenLockIsPresent(): void127- {128-$gaugeLockKey = sprintf('%s-process-manager-lock', self::UPDATE_TARGET);129122130-Redis::shouldReceive('get')->once()->with($gaugeLockKey)->andReturn(true);123+Log::shouldReceive('debug')131-Redis::shouldReceive('set')->never();124+ ->once()132-Redis::shouldReceive('expire')->never();125+ ->with('[ EsUpdateProcessManager ] Empty selection', ['update_target' => self::UPDATE_TARGET]);133126134- Datadog::shouldReceive('increment')->once()->withAnyArgs();127+$this->statsReporter->expects($this->never())->method('report');135- Datadog::shouldReceive('gauge')->never();136128137-$processor = $this->getProcessor();129+$processor = new UpdateProcessManager(138-$processor->setEnvironment('staging');130+ esClient: $this->getEsClientMock(),131+ entitySelector: $entitySelector,132+ batchStatusManager: $batchStatusManager,133+ deleteDocumentsAction: $this->createMock(DeleteDocumentsAction::class),134+ upsertDocumentsAction: $this->createMock(UpsertDocumentsAction::class),135+ loadDocumentsAction: $this->createMock(LoadDocumentsAction::class),136+ statsReporter: $this->statsReporter,137+ );138+$processor->setEnvironment(self::ENVIRONMENT);139+$processor->setUpdateTarget(self::UPDATE_TARGET);140+$processor->bootstrap();139141140-$processor->doUpdateEntitiesChunk();142+$this->assertFalse($processor->doUpdateEntitiesChunk());141 }143 }142144143public function testRunDoUpdateButThrottled(): void145public function testRunDoUpdateButThrottled(): void144 {146 {145$this->isThrottled = true;147$this->isThrottled = true;146148147-$this->silenceDatadogAndRedisLock();149+ Log::shouldReceive('info')->withAnyArgs();150+151+$this->statsReporter->expects($this->once())->method('report');148152149// Reschedule High priority153// Reschedule High priority150 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);154 Redis::shouldReceive('saddarray')->with('activities-for-update-priority', $this->highPriority);151// Reschedule low priority155// Reschedule low priority152 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);156 Redis::shouldReceive('saddarray')->with('activities-for-update', $this->normalPriority);153157158+$this->prepareStatusManager(1);159+154$processor = $this->getProcessor();160$processor = $this->getProcessor();155161156$this->assertTrue($processor->doUpdateEntitiesChunk());162$this->assertTrue($processor->doUpdateEntitiesChunk());@@ -165,10 +171,11 @@ private function getProcessor(): UpdateProcessManager165 deleteDocumentsAction: $this->getDeleteActionMock(),171 deleteDocumentsAction: $this->getDeleteActionMock(),166 upsertDocumentsAction: $this->getUpsertActionMock(),172 upsertDocumentsAction: $this->getUpsertActionMock(),167 loadDocumentsAction: $this->getLoadDocumentsMock(),173 loadDocumentsAction: $this->getLoadDocumentsMock(),174+ statsReporter: $this->statsReporter,168 );175 );169176170$updateProcessor->setUpdateTarget($this->updateTargetEntity);177$updateProcessor->setUpdateTarget($this->updateTargetEntity);171-$updateProcessor->setEnvironment('test-env');178+$updateProcessor->setEnvironment(self::ENVIRONMENT);172179173$updateProcessor->bootstrap();180$updateProcessor->bootstrap();174181@@ -195,23 +202,6 @@ private function getEsClientMock(): Client|MockObject195return $clientMock;202return $clientMock;196 }203 }197204198-private function prepareLogger(): void199- {200- Log::shouldReceive('info')201- ->atLeast()202- ->once()203- ->with('[ EsUpdateProcessManager ] Finished updating entities in ES', $this->anything());204- }205-206-private function silenceDatadogAndRedisLock(): void207- {208- Datadog::shouldReceive('increment')->atLeast()->once()->withAnyArgs();209- Datadog::shouldReceive('gauge')->withAnyArgs();210- Redis::shouldReceive('get')->withAnyArgs()->andReturn(null);211- Redis::shouldReceive('set')->withAnyArgs();212- Redis::shouldReceive('expire')->withAnyArgs();213- }214-215private function getDeleteActionMock(): DeleteDocumentsAction|MockObject205private function getDeleteActionMock(): DeleteDocumentsAction|MockObject216 {206 {217$deleteAction = $this->createMock(DeleteDocumentsAction::class);207$deleteAction = $this->createMock(DeleteDocumentsAction::class);@@ -320,26 +310,30 @@ private function mockSelection(): SelectionList|MockObject320return $selectionList;310return $selectionList;321 }311 }322312323-private function prepareStatusManager(): void313+private function prepareStatusManager(int $invokeTimes = 0): void324 {314 {325$batchStatusManager = $this->createMock(BatchStatusManager::class);315$batchStatusManager = $this->createMock(BatchStatusManager::class);326316327-$batchStatusManager->expects($this->atLeastOnce())317+if ($invokeTimes) {318+$batchStatusManager->expects($this->once())319+ ->method('setUpdateTarget')320+ ->with(self::UPDATE_TARGET);321+ } else {322+$batchStatusManager->expects($this->never())->method('setUpdateTarget');323+ }324+325+$batchStatusManager->expects($this->exactly($invokeTimes))328 ->method('generateName')326 ->method('generateName')329 ->willReturn(self::BATCH_NAME);327 ->willReturn(self::BATCH_NAME);330328331-$batchStatusManager->expects($this->atLeastOnce())329+$batchStatusManager->expects($this->exactly($invokeTimes))332- ->method('setUpdateTarget')333- ->with(self::UPDATE_TARGET);334-335-$batchStatusManager->expects($this->atLeastOnce())336 ->method('scheduleWork')330 ->method('scheduleWork')337 ->with(331 ->with(338array_merge($this->highPriority, $this->normalPriority),332array_merge($this->highPriority, $this->normalPriority),339self::BATCH_NAME333self::BATCH_NAME340 );334 );341335342-$batchStatusManager->expects($this->atLeastOnce())336+$batchStatusManager->expects($this->exactly($invokeTimes))343 ->method('finishWork')337 ->method('finishWork')344 ->with(self::BATCH_NAME);338 ->with(self::BATCH_NAME);345339</selection>” selected.
Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
Expand
Copy prompt
Gemini said
Gemini said
Here is a summary of the changes in the provided git diff for
UpdateProcessManagerTest.php
:...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
84009
|
2898
|
20
|
2026-05-28T11:18:25.139704+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779967105139_m2.jpg...
|
Firefox
|
Jy 20910 schedule parallel update target processin Jy 20910 schedule parallel update target processing by Vasil-Jiminny · Pull Request #12130 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12130/changes#diff-222 github.com/jiminny/app/pull/12130/changes#diff-222bc92583c5030061f1478686b8441263e32426fefdfbe6fe27c8271e2c3acb...
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
-2112793529402417778
|
4739293140786619618
|
visual_change
|
hybrid
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
rircroxviehhsttonooonnurnPotLe.lootWindowHelp• =github.com/v Gooc e GeminiGemini 3.1 Pro ~• Thu 28 May 14:18:243с503006111478686b8441263e32426fefdfbe6fe27c8271e2c3ach.•• XPipelines - jiminny/app(JY-20613) Allow owner's role to bText relayDeleted object erAxUemered tines on New codJY-20963 fix deleted object impJiminny\Exceptions(EmailActivityfrM Inbox (1,733) - luias.kovaliklimirioonre Reso ve php 81.15 ded8 Jiminm,Platform Sorint 5.02 - Platform Te8 Jiminny7 (SRD-6881] (On demand) TransSona Strbramaal an at 27/05/2021aIliyana Netseva at 27/05/2026, 1€es20910 schadule oarliel ne.— Now Tabiginore lests for now. Just tocus on non test filesI'd be happy to review the implementation code, but the git diff you provided only contains changesto a single test file: UpdateProcessManagerTest.phpBecause the actual source files (such as UpdateProcessManager.php orReindexTargetStatsReporter.php ) are not included in the snippet, I cannot analyze them forpotential issuesItvou orovide the code or the dift for the non-test files. I will cladiv review them for lodic flaws.architectural risks, or pertormance concerns.@ i OpenJy 20910 schedule parallel uodate target processing 81230All commits - Vasil-Jiminny wants to merge 65 commits into master from JY-20910-schedule-parallel-update-target-processing|CFilter tec.• E app|v = Component/ESEntityTypeReindexer.php• ReindexTargetStatsReporter.p_3) UodateProcessManager.phpv Console= Commands/ElasticsearchAsyncUpdateEsEntities.php•1AsvncUodateSupervisor.oho- DeleteEmailDocumentsCom…•)ReindexEntityTypes.php•1 RemoveGhostParticipantsCo….8 ResetAsyncElasticSearchCo..3) Kernel.phplv -Contracts/EgStopSignallnterface.phpv TraitsP GracefullvStonoable.ohov F tectsfllnt/Comnonent/FSl•) EntityTvpeReindexerTest.phpapp/Console/Comnands/Elasticsearch/AsyncUpdateSupervisor.php L•) ReindexTargetStatsReporterTes…UpdateProcessManagerTest.phpsô:ASX GeminilYor lim now chate thn" uend to imntoy our modale Camioie Alit cao mata mttrkae co donbld chachit Yoir mracy & CaminiSummarize page© 2 /15 viewedAnaitns approvViewedLoa:: tntor' Es/AsynclodateSuceryscorShutttne dowpid = getnypid),'children' => array_values(Sthis->childPids),sthas"arkkeacylostoplthisessionalHandlerSoutcountpuotac tunction handtel). vozaLog:: info('( Es/AsyncUpdateSupervisor ] Starting supervisor'. ["pid" a> getnypido),'targets' => UpdateTarget::allowedTargets(),Sthis->setMessageOnExit(*Es/AsyncUpdateSupervisor received SIGINT or SIGTERM.*)=foreach (UpdateTarget::allowedTargets() as Starget) ‹sthis-schildPidsistarget = Sthis-storidiorker(Staroet):chfle (true) &torcach sthis-chtldPtds as staroer 8 50107// pcntl_waitpid() called with WNOHANG is non-blocking, it checks if aPid child process has exitedi/ It will return the same PID if the child process has terminated81t the child process is still nunning, or = no such oroces.SterminatedPids ocnt mttotd sotd. Sotatus. WohANGChild process does not existli4 (sterninatedpid een ct lt t CchiccachallCton)dLoc::error' Es/AsyncuodateSuoervisor Exoected child process doegnt aviet easanuntant"target" => Starget."niat etniasthis-schildPids staroet. a sthis-storkworker(staroct)#Chiid neareee hae eviten1t (Sterninatedpid a= Soid 86 ! Sthis-sshallStoo) ‹|...
|
84008
|
NULL
|
NULL
|
NULL
|