|
85267
|
2920
|
12
|
2026-05-28T12:16:03.999350+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970563999_m1.jpg...
|
Slack
|
Vasil Vasilev (DM) - Jiminny Inc - 3 new items - S Vasil Vasilev (DM) - Jiminny Inc - 3 new items - Slack...
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":8,"on_screen":true,"role_description":"text"}]...
|
802487558813652629
|
-8120845942623094601
|
typing_pause
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
PhpStormFileEditViewNavigateCodeRefactorRunToolsGitWindowHelpec2-user@ip-10-30-129-190:~screenpipe"84‹$0(ah]A100% <78• Thu 28 May 15:16:03181ec2-user@ip-10-30-140-...₴7DOCKER#_####_#####\\###||\#/V~'881DEV (-zsh)O [EMAIL] Linux 2023 (ECS Optimized)_/m/For documentation, visit [URL_WITH_CREDENTIALS] ~]$ exitlogoutConnection to jiminny-prod-ecsi closed.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ applukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ vprodWarning: Permanently added 'jiminny-prod-ecs1' (ED25519) to the list of known hosts.A newer release of "Amazon Linux" is available.Version 2023.10.20260330:Version 2023.11.20260406:Version 2023.11.20260413:Version2023.11.20260427:Version2023.11.20260505:Version 2023.11.20260509:Version 2023.11.20260511:Version 2023.11.20260514:Run "/usr/bin/dnf check-release-update" for full release and version update info#_~\ ####_\ #####\\###1\#/Amazon Linux 2023 (ECS Optimized)/m/'For documentation, visit [URL_WITH_CREDENTIALS] ~]$ client_loop: send disconnect: Broken pipeukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-relay) $I...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85266
|
2921
|
13
|
2026-05-28T12:16:01.829752+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970561829_m2.jpg...
|
Slack
|
Vasil Vasilev (DM) - Jiminny Inc - 3 new items - S Vasil Vasilev (DM) - Jiminny Inc - 3 new items - Slack...
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"bounds":{"left":0.5056516,"top":0.058260176,"width":0.011968086,"height":0.028731046},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"bounds":{"left":0.50299203,"top":0.10055866,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"bounds":{"left":0.50664896,"top":0.13806863,"width":0.009973404,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"bounds":{"left":0.50299203,"top":0.15482841,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":8,"bounds":{"left":0.50764626,"top":0.19233839,"width":0.007978723,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":6,"bounds":{"left":0.50299203,"top":0.20909816,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":8,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.012965426,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.0026595744,"height":0.011173184}},{"char_start":1,"char_count":7,"bounds":{"left":0.50764626,"top":0.24660814,"width":0.010638298,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":6,"bounds":{"left":0.50299203,"top":0.26336792,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":8,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0076462766,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5099734,"top":0.3008779,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Later","depth":6,"bounds":{"left":0.50299203,"top":0.31763768,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Later","depth":8,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.008643617,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5093085,"top":0.35514766,"width":0.0066489363,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"More…","depth":6,"bounds":{"left":0.50299203,"top":0.3719074,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"More","depth":8,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.008976064,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.0033244682,"height":0.011173184}},{"char_start":1,"char_count":3,"bounds":{"left":0.5106383,"top":0.4094174,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"}]...
|
-8110235827886994960
|
-8111871699717769025
|
click
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
SIUCKVIChRotonWindowHelpPwovscors#12121 on JY-20963-foc-proidetecanyice pn.ne beloers.ohtnelereooiecistraicon:SamiceTesuphr©ActivityControlier.php=custom.loglaravel.log© VoiceConsentPrefix.phpen Noticationsv Observers© AccountObserver.phpCyActwwooserver.pnp© ContactObserver.phgGroupObserver.pho© LeadObserver.phoC ProfileObserver.phpC SocialAccountObserver.php© UserObserver.phoUserRoleObserver.pho> (l Policiesa ProvidersCn Queueu Reoositonie> Ea RulesvserviceDa ActivityaireoonM Avatallealendara Bullhome CopperimermobiacteNacorate A chivin> @ Dummym Helnarsv im Hibsod(i) AccountSyncStrategMAetioneD ContactSyncStrateay› DDTO> Ea Fieldswn taueeaOLeAkоkyscrco.onO UserSHStoy-prp© Team.phpe KecneupnisA console [STAGINGTeorcolmererestonC TextRelayServiceTest.phg(©) Hubspot.JournalPollinaService.ohp x ptp autoload.ohrcass nuosoorsournalroco noserveana lock to orevent auloole instances.3073esePolLingLock: bool— 78%78578705786›addSeconds(self::LOCK_VTL_SECONDS) ->tolS0StringO:GAREEE31731888an theat hothtoek ann ayns.matsondtCoyns noeht> now()->toIS0StringO711712=213-74715f Not eXists) for atonic lock acquisitionis::set(key: self::POLLING LOCK KEY, ison encode(SlockData), options: 'EX", self::LOCK TTL SECONDS, *NX*)=Renewal = tineo,100: "[HubSpot Journal Polbingl Acquired polting lock".[• => SexojinesAt.717-218En9728)722723$ 332933133373PolLinglock@= woidt733C UTHAAAARAAAA734C HubspotDea/Wobhoolx 346735(C) Hubspot.JournalApiClielling lock (for emergency situations)© Hubspot.JournalPolling! 348@ HubspotWebhookSubr© .JournalAoiResutt.oho› LeaseLock(): voidf...}© JournalBatchSizelimitEC) Journa Eventtranstormervice to stop gracefullya Metadata@poortunityswncstrateo→lmlpae natioo• Stop@: void(...}SanncetitaiteTX: AUTONAND a.created_at › DATE_:GROUP BY u.id, u.email,ORDER BY sne count DESMselect + Eron teans, wherlselect + Eron coles,CEIEOTCONCATU.Id, CASE WHsa.*t.ouner id FROM sociJOIN users u on u.id = sJOIN teans t 1.n<->1: onWHERE u.tean_id = 1117 aSELECT * FROM actávitioSELECT * FROM actávitioSELECT * FROM crn configSELECT # FROM teans WHERselleetron usens whenselect * fron playbooksseleetron miawhonkeselect + fron olavbookseleet ron eoeselect * fron crn_field.SELECT * FROM crn_field_JOTM con Belds + 0M 44• JOIN activities a ON $NHERF Actvity 3d= 70073AND € con onovider saSELECT * FROM activity.mselect * fron users whenPARAtT GAAR MANGUREANOPAlRetGhAn dAAAIRdAMPolhnttene neard wharselect * fron teans wherPhat"toon actytysselect * fron activitysDMsActivityLateMonJiminnY ….# backend# buescontusion-dinig# donut_time#enpineerine# general# hapoy birthdavA infocoe intemal all# infra-chansed# infrastructure de#bu-team-infoi liminnv-be# platform-team# platform-ticketstoroduct launche# random# release# suppor# thank-youssie the neoole of fimill6? Direct message.Vasil VasilenF8. Stefka Stoyanova1a llivana NetsevaA Ctovan TomnulPetko KashinskiGola Nimitrous: Todor Stamatol1 Stelivan Georsie.D Vod&r MireNikolav Vanko&. James GrahamLukas Kovalky7o0sLXind co mey to.lo.u@ Describe what you are looking forVasil Vasileve MessagerNoR0d canvisfiles.+Vasil Vasilev 2:56 PM1 с добър коментарDoory2e intentionaЗ сьщо e intentional поради факта, че phpredis dniver-a не поддьржа set ex +nх параметри, и тряова да се пуснат две операции set + expireLukas Kovalik 3.07 PMок, зз го пуснах пак поез gеmіnіlза третата точка обаче наистина ли няма подьржкааз май си ги ползвам някьлеVasil Vasilev 3:10 PMне става, бях го направил така, и се счупиLukas Kovalik 3:10 PMами и при мен се чумешеVasil Vasilev 3:11 PMpredis поддьржа set(Skey. Svalue. nx' - true, ex =60)Cnhnranic He caRaLukas Kovalik 3.14pNтака май не работеше Sresult = Redis:set(StestKey, StestValue, 'EX, Stti, "NX"): а така да Sresult = Redis:set(StestKey, StestValue, ['nx, "ex' => $ttl]);Vasil Vasiley 2.11 pwLukas Kovalik 3.12 pNне помно BеUEVasil Vasilev 3:12 PMobоитноtо може nаeLukas Kovalik 3-12 PMможе и ла брькамewons uusSlockAcquired - Redis::set(self::POLLING LOCK KEY, ison encode(SlockData). "EX', self::LOCK TTL SECONDS. *NX*))значи пьрвото работиLukas Kovalik 313 PM...
|
85264
|
NULL
|
NULL
|
NULL
|
|
85265
|
2920
|
11
|
2026-05-28T12:16:01.506628+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970561506_m1.jpg...
|
Slack
|
Vasil Vasilev (DM) - Jiminny Inc - 3 new items - S Vasil Vasilev (DM) - Jiminny Inc - 3 new items - Slack...
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"on_screen":true,"role_description":"text"}]...
|
6813202753771723310
|
-5814828648103331082
|
click
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
PhpStormFileEditViewNavigateCodeRefactorRunToolsGitWindowHelpec2-user@ip-10-30-129-190:~screenpipe"€ 884‹$0(ah]A100% <78• Thu 28 May 15:16:01181ec2-user@ip-10-30-140-...₴7DOCKER#_####_#####\\###||\#/V~'881DEV (-zsh)O [EMAIL] Linux 2023 (ECS Optimized)_/m/For documentation, visit [URL_WITH_CREDENTIALS] ~]$ exitlogoutConnection to jiminny-prod-ecsi closed.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ applukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ vprodWarning: Permanently added 'jiminny-prod-ecs1' (ED25519) to the list of known hosts.A newer release of "Amazon Linux" is available.Version 2023.10.20260330:Version 2023.11.20260406:Version 2023.11.20260413:Version2023.11.20260427:Version2023.11.20260505:Version 2023.11.20260509:Version 2023.11.20260511:Version 2023.11.20260514:Run "/usr/bin/dnf check-release-update" for full release and version update info#_~\ ####_\ #####\\###1\#/Amazon Linux 2023 (ECS Optimized)/m/'For documentation, visit [URL_WITH_CREDENTIALS] ~]$ client_loop: send disconnect: Broken pipeukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-relay) $I...
|
85262
|
NULL
|
NULL
|
NULL
|
|
85264
|
2921
|
12
|
2026-05-28T12:15:59.140727+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970559140_m2.jpg...
|
PhpStorm
|
faVsco.js – HubspotJournalPollingService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
#12121 on JY-20963-fix-im Project: faVsco.js, menu
#12121 on JY-20963-fix-import-on-deleted-entity, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
12
9
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Hubspot\Journal;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
use Jiminny\Models\Team;
use Jiminny\Repositories\Crm\CrmConfigurationRepository;
use Jiminny\Repositories\TeamRepository;
use Jiminny\Services\Crm\Hubspot\Webhook\WebhookEventProcessor;
class HubspotJournalPollingService
{
private const string [ENV_SECRET];
private const string [ENV_SECRET];
private const string [ENV_SECRET];
private const int LOCK_TTL_SECONDS = 120; // 2 minutes - renewed every 30 seconds
private const int LOCK_RENEWAL_INTERVAL = 30; // Renew lock every 30 seconds
private const int BASE_SLEEP_SECONDS = 5; // Base sleep when no data
private const int MAX_SLEEP_SECONDS = 120; // Maximum sleep duration
private const int EMPTY_THRESHOLD_FOR_BACKOFF = 3; // Empty results before increasing sleep
private const int MAX_CYCLES_DEFAULT = 3000; // Default maximum cycles before stopping
private const int MEMORY_CRITICAL_THRESHOLD = 90; // 90% of memory limit
private const int MAX_BACKOFF_SECONDS = 300;
private const int MAX_OFFSET_RETRIES = 3;
private const int MAX_RUNTIME_SECONDS = 240; // 4 minutes
private const int MAX_EMPTY_RESULTS_BEFORE_EXIT = 5;
private const int LOG_INTERVAL_CYCLES = 10;
private bool $shouldStop = false;
private int $consecutiveEmptyResults = 0;
private array $offsetRetryCount = [];
private int $cycleCount = 0;
private int $startTime = 0;
private int $lastLockRenewal = 0;
private float $totalApiTime = 0;
private float $totalDownloadTime = 0;
private float $totalTransformTime = 0;
private float $totalProcessTime = 0;
private int $totalJournalFilesDownloaded = 0;
private int $totalEventsProcessed = 0;
private int $emptyJournalFiles = 0;
private int $otherPortalSkipped = 0;
public function __construct(
private HubspotJournalApiClient $apiClient,
private JournalEventTransformer $transformer,
private WebhookEventProcessor $eventProcessor
) {
}
/**
* Start continuous polling of the HubSpot journal
*/
public function startPolling(): void
{
$this->startTime = time();
$this->cycleCount = 0;
$this->logPollingStart();
if (! $this->acquirePollingLock()) {
Log::warning('[HubSpot Journal Polling] Another polling process is already running');
return;
}
try {
while ($this->shouldContinuePolling()) {
$this->cycleCount++;
$this->executePollingCycle();
}
} catch (\Throwable $e) {
Log::error('[HubSpot Journal Polling] Error while polling', [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
]);
} finally {
$this->cleanupPollingSession();
}
}
/**
* Perform a single polling cycle
* Returns true if work was found and processed, false if no work available, null if entry was skipped
*/
public function pollOnce(): ?bool
{
$currentOffset = $this->getCurrentOffset();
$apiStart = microtime(true);
$apiResult = $currentOffset === null
? $this->apiClient->getLatestJournalEntry()
: $this->apiClient->getNextJournalEntry($currentOffset);
$this->totalApiTime += (microtime(true) - $apiStart) * 1000;
if (! $apiResult->success) {
return $this->handleApiResult($apiResult, $currentOffset ?? 'latest');
}
if ($apiResult->data === null) {
Log::info('[HubSpot Journal Polling] No data');
return false;
}
$offset = $apiResult->data['currentOffset'];
$s3Url = $apiResult->data['url'];
$retryCount = $this->offsetRetryCount[$offset] ?? 0;
$downloadStart = microtime(true);
$downloadResult = $this->apiClient->downloadJournalFile($s3Url);
$this->totalDownloadTime += (microtime(true) - $downloadStart) * 1000;
if (! $downloadResult->success) {
return $this->handleDownloadResult($downloadResult, $offset, $retryCount);
}
$this->totalJournalFilesDownloaded++;
$journalData = $downloadResult->data;
$transformStart = microtime(true);
try {
$transformedEvents = $this->transformer->transformJournalEvents($journalData);
} catch (\Exception $e) {
return $this->handleTransformationFailure($offset, $retryCount, $e);
}
$this->totalTransformTime += (microtime(true) - $transformStart) * 1000;
unset($journalData);
$processStart = microtime(true);
$eventsCount = count($transformedEvents);
$this->totalEventsProcessed += $eventsCount;
if ($eventsCount === 0) {
$this->emptyJournalFiles++;
} else {
$this->eventProcessor->processEvents($transformedEvents, '[HubSpot Journal Polling]');
}
$this->totalProcessTime += (microtime(true) - $processStart) * 1000;
$this->updateOffset($offset);
unset($transformedEvents);
$this->logProgressIfNeeded();
return $eventsCount > 0;
}
private function logProgressIfNeeded(): void
{
if ($this->cycleCount === 0 || $this->cycleCount % self::LOG_INTERVAL_CYCLES !== 0) {
return;
}
$cycles = $this->cycleCount;
$avgTotal = ($this->totalApiTime + $this->totalDownloadTime + $this->totalTransformTime + $this->totalProcessTime) / $cycles;
Log::info('[HubSpot Journal Polling] Progress', [
'cycles' => $cycles,
'files' => $this->totalJournalFilesDownloaded,
'events' => $this->totalEventsProcessed,
'empty_files' => $this->emptyJournalFiles,
'avg_ms' => round($avgTotal, 1),
'avg_api_ms' => round($this->totalApiTime / $cycles, 1),
'avg_download_ms' => round($this->totalDownloadTime / $cycles, 1),
'avg_transform_ms' => round($this->totalTransformTime / $cycles, 1),
'avg_process_ms' => round($this->totalProcessTime / $cycles, 1),
]);
}
/**
* Get the current polling offset from Redis
*/
private function getCurrentOffset(bool $cacheOnly = false): ?string
{
$offset = Redis::get(self::OFFSET_CACHE_KEY);
if (! $offset && ! $cacheOnly) {
$offset = $this->getDbOffset();
}
return $offset ? (string) $offset : null;
}
/**
* Get the last stored offset from the database
*/
public function getDbOffset(): ?string
{
$jiminnyTeam = $this->getJiminnyTeam();
if (! $jiminnyTeam instanceof Team) {
Log::error('[HubSpot Journal Polling] Jiminny team not found');
return null;
}
$crmRepository = app(CrmConfigurationRepository::class);
$offset = $crmRepository->getSetting($jiminnyTeam->getCrmConfiguration(), 'hubspot_journal_offset');
Log::info('[HubSpot Journal Polling] Getting offset from database', [
'offset' => $offset,
'jiminny_team_id' => $jiminnyTeam->getId(),
]);
return $offset;
}
/**
* Reset the database offset
*/
public function resetDbOffset(): void
{
$jiminnyTeam = $this->getJiminnyTeam();
if (! $jiminnyTeam instanceof Team) {
Log::error('[HubSpot Journal Polling] Jiminny team not found');
return;
}
$crmRepository = app(CrmConfigurationRepository::class);
$crmRepository->updateSetting($jiminnyTeam->getCrmConfiguration(), 'hubspot_journal_offset', '');
Log::info('[HubSpot Journal Polling] Database offset reset');
}
private function getJiminnyTeam(): ?Team
{
$teamRepository = app(TeamRepository::class);
return $teamRepository->getTeamBySlug('jiminny');
}
private function updateDbOffset(string $offset): void
{
$jiminnyTeam = $this->getJiminnyTeam();
if (! $jiminnyTeam instanceof Team) {
Log::error('[HubSpot Journal Polling] Jiminny team not found');
return;
}
$crmRepository = app(CrmConfigurationRepository::class);
$crmRepository->updateSetting($jiminnyTeam->getCrmConfiguration(), 'hubspot_journal_offset', $offset);
}
/**
* Update the polling offset
*/
private function updateOffset(string $offset): void
{
Redis::setex(self::OFFSET_CACHE_KEY, 259200, $offset); // 3 days TTL
$this->clearOffsetRetryCount($offset);
}
/**
* Reset the polling offset
*/
public function resetOffset(): void
{
Redis::del(self::OFFSET_CACHE_KEY);
Log::info('[HubSpot Journal Polling] Reset polling offset');
}
/**
* Set a specific offset (for manual override or recovery)
*/
public function setOffset(string $offset): void
{
$this->updateOffset($offset);
Log::warning('[HubSpot Journal Polling] Offset manually set', [
'offset' => $offset,
]);
}
/**
* Get current polling status
*/
public function getPollingStatus(): array
{
$lockDataJson = Redis::get(self::POLLING_LOCK_KEY);
$lockData = $lockDataJson ? json_decode($lockDataJson, true) : null;
return [
'is_locked' => $lockData !== null,
'current_offset' => $this->getCurrentOffset(),
'lock_expires_at' => $lockData['expires_at'] ?? null,
'lock_acquired_at' => $lockData['acquired_at'] ?? null,
];
}
/**
* Acquire exclusive polling lock to prevent multiple instances
*/
private function acquirePollingLock(): bool
{
$expiresAt = now()->addSeconds(self::LOCK_TTL_SECONDS)->toISOString();
// Use atomic operation to set both lock and expiration data
$lockData = [
'locked' => true,
'expires_at' => $expiresAt,
'acquired_at' => now()->toISOString(),
];
// Use SETNX (SET if Not eXists) for atomic lock acquisition
$lockAcquired = Redis::set(self::POLLING_LOCK_KEY, json_encode($lockData), 'EX', self::LOCK_TTL_SECONDS, 'NX');
if ($lockAcquired) {
$this->lastLockRenewal = time();
Log::info('[HubSpot Journal Polling] Acquired polling lock', [
'expires_at' => $expiresAt,
]);
}
return (bool) $lockAcquired;
}
/**
* Release the polling lock
*/
private function releasePollingLock(): void
{
Redis::del(self::POLLING_LOCK_KEY);
Log::info('[HubSpot Journal Polling] Released polling lock');
}
/**
* Force release the polling lock (for emergency situations)
*/
public function forceReleaseLock(): void
{
$this->releasePollingLock();
Log::warning('[HubSpot Journal Polling] Force released polling lock');
}
/**
* Signal the polling service to stop gracefully
*/
public function requestStop(): void
{
Redis::setex(self::STOP_FLAG_KEY, 300, '1'); // 5 minutes TTL
$this->shouldStop = true;
Log::info('[HubSpot Journal Polling] Stop requested');
}
/**
* Check if polling should stop
*/
private function shouldStop(): bool
{
// Check local flag first (faster)
if ($this->shouldStop) {
return true;
}
// Check Redis flag (for external stop requests)
if (Redis::exists(self::STOP_FLAG_KEY)) {
$this->shouldStop = true;
return true;
}
return false;
}
/**
* Clear the stop flag and reset state to allow service to start
*/
public function clearStopFlag(): void
{
Redis::del(self::STOP_FLAG_KEY);
$this->shouldStop = false;
$this->resetPollingState();
Log::info('[HubSpot Journal Polling] Stop flag cleared and state reset');
}
/**
* Reset polling state without clearing stop flag
*/
private function resetPollingState(): void
{
$this->consecutiveEmptyResults = 0;
$this->cycleCount = 0;
$this->startTime = 0;
$this->totalApiTime = 0;
$this->totalDownloadTime = 0;
$this->totalTransformTime = 0;
$this->totalProcessTime = 0;
$this->totalJournalFilesDownloaded = 0;
$this->totalEventsProcessed = 0;
$this->emptyJournalFiles = 0;
$this->otherPortalSkipped = 0;
}
public function hasStopFlag(): bool
{
return (bool) Redis::exists(self::STOP_FLAG_KEY);
}
/**
* Calculate adaptive sleep duration based on consecutive empty results
*/
private function calculateAdaptiveSleep(): int
{
if ($this->consecutiveEmptyResults < self::EMPTY_THRESHOLD_FOR_BACKOFF) {
return self::BASE_SLEEP_SECONDS; // 5 second
}
// Progressive backoff: 15s -> 30s -> 60s -> 120s (max)
$delay = 3 * self::BASE_SLEEP_SECONDS;
$sleepDuration = $delay * (2 ** ($this->consecutiveEmptyResults - self::EMPTY_THRESHOLD_FOR_BACKOFF));
return min($sleepDuration, self::MAX_SLEEP_SECONDS);
}
private function logPollingStart(): void
{
Log::info('[HubSpot Journal Polling] Service starting', [
'memory_limit' => ini_get('memory_limit'),
'max_execution_time' => ini_get('max_execution_time'),
'initial_memory_mb' => round(memory_get_usage(true) / 1024 / 1024, 2),
]);
}
/**
* Log polling service end information
*/
private function logPollingEnd(): void
{
$runtime = time() - $this->startTime;
$cycles = max($this->cycleCount, 1);
Log::info('[HubSpot Journal Polling] Service ending', [
'runtime_seconds' => $runtime,
'total_cycles' => $this->cycleCount,
'files_downloaded' => $this->totalJournalFilesDownloaded,
'empty_files' => $this->emptyJournalFiles,
'other_portal_skipped' => $this->otherPortalSkipped,
'total_events' => $this->totalEventsProcessed,
'events_per_file' => $this->totalJournalFilesDownloaded > 0
? round($this->totalEventsProcessed / $this->totalJournalFilesDownloaded, 1)
: 0,
'avg_api_ms' => round($this->totalApiTime / $cycles, 1),
'avg_download_ms' => round($this->totalDownloadTime / $cycles, 1),
'avg_transform_ms' => round($this->totalTransformTime / $cycles, 1),
'avg_process_ms' => round($this->totalProcessTime / $cycles, 1),
'peak_memory_mb' => round(memory_get_peak_usage(true) / 1024 / 1024, 2),
]);
}
/**
* Improved stop condition check with clear reasoning
*/
private function shouldContinuePolling(): bool
{
// Check explicit stop request first (fastest check)
if ($this->shouldStop()) {
Log::info('[HubSpot Journal Polling] Stop requested, ending polling');
return false;
}
if ($this->consecutiveEmptyResults >= self::MAX_EMPTY_RESULTS_BEFORE_EXIT) {
Log::warning('[HubSpot Journal Polling] Maximum empty results reached, stopping', [
'empty_results' => $this->consecutiveEmptyResults,
'max_empty_results' => self::MAX_EMPTY_RESULTS_BEFORE_EXIT,
]);
return false;
}
// Check runtime limit (4 minutes)
$runtime = time() - $this->startTime;
if ($runtime >= self::MAX_RUNTIME_SECONDS) {
Log::warning('[HubSpot Journal Polling] Maximum runtime reached, stopping', [
'runtime_seconds' => $runtime,
'runtime_minutes' => round($runtime / 60, 1),
'max_runtime_seconds' => self::MAX_RUNTIME_SECONDS,
]);
return false;
}
// Check memory limits (prevent OOM)
$currentMemory = memory_get_usage(true);
$memoryLimitBytes = $this->parseMemoryLimit(ini_get('memory_limit'));
if ($memoryLimitBytes > 0 && $currentMemory > ($memoryLimitBytes * self::MEMORY_CRITICAL_THRESHOLD / 100)) {
Log::warning('[HubSpot Journal Polling] Memory limit approaching, stopping', [
'current_memory_mb' => round($currentMemory / 1024 / 1024, 2),
'memory_limit' => ini_get('memory_limit'),
'usage_percent' => round(($currentMemory / $memoryLimitBytes) * 100, 1),
]);
return false;
}
// Check for excessive cycles (prevent runaway processes)
if ($this->cycleCount > self::MAX_CYCLES_DEFAULT) {
Log::warning('[HubSpot Journal Polling] Maximum cycles reached, stopping', [
'cycles' => $this->cycleCount,
'max_cycles' => self::MAX_CYCLES_DEFAULT,
]);
return false;
}
return true;
}
/**
* Handle when work is found - reset counters and continue immediately
*/
private function handleWorkFound(): void
{
$this->consecutiveEmptyResults = 0;
}
/**
* Handle when no work is found - implement adaptive sleep
*/
private function handleNoWorkFound(): void
{
$this->consecutiveEmptyResults++;
$sleepDuration = $this->calculateAdaptiveSleep();
Log::debug('[HubSpot Journal Polling] No work found, sleeping', [
'consecutive_empty' => $this->consecutiveEmptyResults,
'sleep_seconds' => $sleepDuration,
'cycle' => $this->cycleCount,
]);
$this->responsiveSleep($sleepDuration);
}
/**
* Sleep with responsive stop checking
*/
private function responsiveSleep(int $seconds): void
{
for ($i = 0; $i < $seconds && $this->shouldContinuePolling(); $i++) {
sleep(1);
}
}
/**
* Parse memory limit string to bytes
*/
private function parseMemoryLimit(string $memoryLimit): int
{
if ($memoryLimit === '-1') {
return 0; // Unlimited
}
$unit = strtolower(substr($memoryLimit, -1));
$value = (int) substr($memoryLimit, 0, -1);
return match ($unit) {
'g' => $value * 1024 * 1024 * 1024,
'm' => $value * 1024 * 1024,
'k' => $value * 1024,
default => (int) $memoryLimit,
};
}
private function executePollingCycle(): void
{
$this->renewLockIfNeeded();
$result = $this->pollOnce();
if ($result === true) {
$this->handleWorkFound();
} elseif ($result === false) {
$this->handleNoWorkFound();
}
}
private function renewLockIfNeeded(): void
{
$now = time();
if ($now - $this->lastLockRenewal >= self::LOCK_RENEWAL_INTERVAL) {
$this->renewPollingLock();
$this->lastLockRenewal = $now;
}
}
private function renewPollingLock(): void
{
$expiresAt = now()->addSeconds(self::LOCK_TTL_SECONDS)->toISOString();
$lockData = [
'locked' => true,
'expires_at' => $expiresAt,
'acquired_at' => now()->toISOString(),
'renewed_at' => now()->toISOString(),
'cycle' => $this->cycleCount,
];
Redis::setex(self::POLLING_LOCK_KEY, self::LOCK_TTL_SECONDS, json_encode($lockData));
Log::debug('[HubSpot Journal Polling] Lock renewed', [
'expires_at' => $expiresAt,
'cycle' => $this->cycleCount,
]);
}
private function handleApiResult(JournalApiResult $result, string $context): bool
{
if ($result->failureType === JournalApiResult::FAILURE_AUTH) {
Log::warning('[HubSpot Journal Polling] Auth failure, will retry next cycle', [
'context' => $context,
]);
return false;
}
if ($result->failureType === JournalApiResult::FAILURE_RATE_LIMIT) {
$waitSeconds = min($result->retryAfterSeconds ?? 60, self::MAX_BACKOFF_SECONDS);
Log::warning('[HubSpot Journal Polling] Rate limit hit, waiting', [
'wait_seconds' => $waitSeconds,
]);
$this->responsiveSleep($waitSeconds);
return false;
}
if ($result->failureType === JournalApiResult::FAILURE_OFFSET_EXPIRED) {
Log::warning('[HubSpot Journal Polling] Offset expired, resetting to fetch latest data', [
'expired_offset' => $context,
]);
$this->resetOffset();
$this->resetDbOffset();
return false;
}
if ($result->isPermanentFailure()) {
Log::error('[HubSpot Journal Polling] Permanent API failure', [
'context' => $context,
'failure_type' => $result->failureType,
'error' => $result->errorMessage,
]);
$this->shouldStop = true;
return false;
}
Log::warning('[HubSpot Journal Polling] Retryable API failure', [
'context' => $context,
'failure_type' => $result->failureType,
'error' => $result->errorMessage,
]);
if ($result->retryAfterSeconds) {
sleep(min($result->retryAfterSeconds, self::MAX_BACKOFF_SECONDS));
}
return false;
}
/**
* Clean up polling session resources
*/
private function cleanupPollingSession(): void
{
$this->logPollingEnd();
$this->storeOffsetInDB();
$this->releasePollingLock();
$this->apiClient->clearPortalCache();
$this->resetPollingState();
}
private function storeOffsetInDB(): void
{
// Save current offset to database before cleanup
$currentOffset = $this->getCurrentOffset(cacheOnly: true);
if ($currentOffset) {
$this->updateDbOffset($currentOffset);
Log::info('[HubSpot Journal Polling] Saved offset to database on cleanup', [
'offset' => $currentOffset,
]);
}
}
private function handleDownloadResult(JournalApiResult $result, string $offset, int $retryCount): ?bool
{
if ($result->failureType === JournalApiResult::FAILURE_UNKNOWN_PORTAL) {
$this->otherPortalSkipped++;
$this->updateOffset($offset);
return null;
}
if ($result->isPermanentFailure()) {
Log::warning('[HubSpot Journal Polling] Permanent failure, skipping offset', [
'offset' => $offset,
'portal_id' => $result->portalId,
'failure_type' => $result->failureType,
'error' => $result->errorMessage,
]);
$this->updateOffset($offset);
$this->clearOffsetRetryCount($offset);
return false;
}
$retryCount++;
if ($retryCount >= self::MAX_OFFSET_RETRIES) {
Log::error('[HubSpot Journal Polling] Max retries reached, skipping offset', [
'offset' => $offset,
'portal_id' => $result->portalId,
'failure_type' => $result->failureType,
'retry_count' => $retryCount,
]);
$this->updateOffset($offset);
$this->clearOffsetRetryCount($offset);
return false;
}
Log::warning('[HubSpot Journal Polling] Retryable failure, will retry', [
'offset' => $offset,
'failure_type' => $result->failureType,
'retry_count' => $retryCount,
'max_retries' => self::MAX_OFFSET_RETRIES,
]);
$this->offsetRetryCount[$offset] = $retryCount;
if ($result->retryAfterSeconds) {
sleep(min($result->retryAfterSeconds, self::MAX_BACKOFF_SECONDS));
}
return false;
}
/**
* Handle transformation failure with retry logic
*/
private function handleTransformationFailure(string $offset, int $retryCount, \Exception $exception): bool
{
$retryCount++;
if ($retryCount >= self::MAX_OFFSET_RETRIES) {
Log::critical('[HubSpot Journal Polling] Max transformation retries reached - SKIPPING offset', [
'offset' => $offset,
'retry_count' => $retryCount,
'error' => $exception->getMessage(),
'trace' => $exception->getTraceAsString(),
]);
// Skip this offset to prevent infinite loop with corrupted data
$this->updateOffset($offset);
$this->clearOffsetRetryCount($offset);
return false;
}
Log::error('[HubSpot Journal Polling] Transformation failed - will retry', [
'offset' => $offset,
'retry_count' => $retryCount,
'max_retries' => self::MAX_OFFSET_RETRIES,
'error' => $exception->getMessage(),
]);
$this->offsetRetryCount[$offset] = $retryCount;
return false;
}
/**
* Clear retry count for an offset after successful processing
*/
private function clearOffsetRetryCount(string $offset): void
{
unset($this->offsetRetryCount[$offset]);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
45
1
41
66
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993
SELECT * FROM users WHERE id = 25061;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 994;
SELECT * FROM crm_profiles WHERE user_id = 25061;
select * from crm_configurations where id = 834;
SELECT * FROM teams WHERE id = 882;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;
SELECT * FROM contacts where crm_configuration_id = 834;
SELECT * FROM opportunities WHERE team_id = 933
# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');
AND id IN (8482561,18352941,19042734,19232139,19445140,19472541);
SELECT * FROM opportunity_contacts
WHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 485; #
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
select crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id
where crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')
# and l.converted_at IS NOT NULL
;
# [PASSWORD_DOTS]
SELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')
and opportunity_id IS NULL
order by id desc;
SELECT * FROM teams WHERE id = 604; # 598
SELECT * FROM activities WHERE id = 74410828; # [EMAIL]
SELECT * FROM accounts WHERE id = 20068382;
SELECT * FROM accounts WHERE id = 35186038;
SELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 559 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;
select * from sidekick_settings where team_id = 781;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100
SELECT * FROM crm_layouts WHERE crm_configuration_id = 711;
SELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL
and is_internal = 0 and status = 'completed'
order by id desc;
SELECT * FROM crm_layout_entities
WHERE crm_layout_id IN (2352, 2353);
;
SELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 556 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;
SELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;
select * from contacts
where crm_configuration_id = 530
and crm_provider_id = 872252;
select * from activities where crm_configuration_id = 530
and user_id = 14343 and type like '%softphone%'
and created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);
SELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t
JOIN crm_configurations c ON t.id = c.team_id
WHERE t.status = 'active';
SELECT * FROM teams where id = 1091;
SELECT * FROM crm_configurations where team_id = 1091;
SELECT * FROM activity_providers where team_id = 1091;
SELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT * FROM teams WHERE name LIKE '%Leadventure%';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1091 and sa.provider = 'salesforce';
SELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812
SELECT * FROM teams where id = 862;
SELECT * FROM crm_configurations where team_id = 862;
SELECT * FROM activity_providers where team_id = 862;
SELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT t.id, crm.id, crm.provider, ap.* FROM teams t
join crm_configurations crm on t.id = crm.team_id
join activity_providers ap on t.id = ap.team_id
where t.status = 'active' and ap.is_enabled = 1
and crm.provider = 'hubspot'
and ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',
'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');
SELECT * FROM teams where id = 1068;
SELECT * FROM crm_configurations where team_id = 1068;
SELECT * FROM activity_providers where team_id = 1068;
SELECT * FROM activities a
where crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')
and a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'
)
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by a.id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1068 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262
SELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
select * from crm_layouts where crm_configuration_id = 834;
select * from crm_layout_entities where crm_layout_id = 2780;
select * from crm_fields where id IN (321153,321192,321193,321194);
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1057 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8
SELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20
SELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10
SELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #
SELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;
select * from users where team_id = 51; # 7783
SELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130
select * from activity_searches where user_id = 7783;
select * from activity_search_filters where activity_search_id IN (32291, 32292);
SELECT asf.activity_search_id, asf.id, asf.value
FROM activity_search_filters asf
WHERE asf.filter = 'group_id'
AND asf.value IN (
SELECT CONCAT(
HEX(SUBSTR(uuid, 5, 4)), '-',
HEX(SUBSTR(uuid, 3, 2)), '-',
HEX(SUBSTR(uuid, 1, 2)), '-',
HEX(SUBSTR(uuid, 9, 2)), '-',
HEX(SUBSTR(uuid, 11))
)
FROM groups
WHERE deleted_at IS NOT NULL
);
SELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where provider = 'hubspot';
SELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133
SELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null
# [PASSWORD_DOTS]
select * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';
select
cp.*
# DISTINCT t.id
# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields
FROM crm_profiles cp
JOIN crm_configurations crm on crm.id = cp.crm_configuration_id
JOIN users u on u.id = cp.user_id
JOIN teams t ON t.id = crm.team_id
WHERE crm.provider = 'salesforce' and t.status = 'active'
and cp.archived_at IS NULL and u.deleted_at IS NULL
and t.id NOT IN (1093)
and t.id = 2
and cp.contact_fields IS NULL;
# and c.crm_provider_id = '003Uu00000ojD4NIAU';
SELECT * FROM users WHERE id = 26484;
SELECT * FROM crm_profiles WHERE user_id = 26484;
SELECT * FROM social_accounts WHERE sociable_id = 26484;
SELECT * FROM crm_configurations where provider = 'salesforce';
select * from users where id IN (10022, 10403);
select * from users where team_id IN (526);
select * from teams where id IN (526, 532);
select * from crm_configurations where id IN (500, 516);
select * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);
select * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 526 and sa.provider = 'salesforce';
select * from team_settings where team_id IN (526, 532);
select * from users where id IN (22824);
select * from crm_profiles where crm_configuration_id IN (1026);
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1093 and sa.provider = 'salesforce';
select * from teams where id = 1099;
select * from users where id = 29643
select * from activity_processing_states;
SELECT * FROM teams where name LIKE '%Fare%'; # 233
SELECT * FROM opportunities where crm_configuration_id = 215
# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'
;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1088 and sa.provider = 'hubspot';
SELECT * FROM teams order by updated_at DESC
SELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account
select * from crm_configurations where provider = 'pipedrive';
select * from teams where id = 957;
select * from crm_configurations where id = 957;
SELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743
SELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;
select * from users where team_id = 1; # 26726 - Gabriela Dureva
SELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific
select * from activities where user_id = 26726 order by id desc;
select * from contacts where crm_configuration_id = 1
and email IN ('[EMAIL]', '[EMAIL]'); # 2094416, 2093620
SELECT * FROM contacts WHERE id = 6284931;
SELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id
WHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;
select * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);
select * from crm_configurations where id = 1;
43801692-1aeb-32ce-acba-5b80a479701a
44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b
405975c0-b3d0-7aaa-821f-09d59cae6dd1
4caf848d-4bed-2299-b248-7788d41f9fca
49bedc3f-f196-eef3-89c3-dea6a3b4aa63
43420989-a09d-b8f8-9806-c8bbf7a02aac
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
SELECT * FROM activities WHERE id = 75461988;
SELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;
select * from contacts where id = 17900517;
select * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id
where crm.provider != 'salesforce';
select * from users where id = 21047;
SELECT * FROM crm_configurations WHERE id = 892;
SELECT * FROM teams WHERE id = 942;
select * from opportunities where team_id = 942 order by updated_at desc;
select * from contacts where team_id = 942 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 942 and sa.provider = 'hubspot';
SELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430
SELECT * FROM crm_configurations WHERE id = 1;
SELECT * FROM teams WHERE crm_id = 1;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
select id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1
SELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430
select * from teams where id = 852;
select * from groups where id = 2286;
select * from sidekick_settings where team_id = 852;
select * from default_activity_types where team_id = 852;
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1 AND u.deleted_at IS NULL
AND u.crm_required = 1
AND u.team_id = 1
ORDER BY u.team_id;
SELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (
18481
);
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1
AND u.deleted_at IS NULL
AND u.crm_required = 1
# AND u.team_id = 1
AND p.id IS NULL -- Move this condition to WHERE clause
ORDER BY u.team_id;
SELECT * FROM opportunities WHERE id = 20002609;
select * from teams where id = 1122; # Velatir, 29953 - [EMAIL]
select * from crm_configurations where id = 1060;
select * from crm_layouts where crm_configuration_id = 1060;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1122 and sa.provider = 'hubspot';
select * from opportunities where team_id = 1122 order by updated_at desc;
select * from crm_field_data where object_type = 'contact';
SELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262
SELECT
CONCAT(u.id, CASE WHEN u.id = t.own...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12121 on JY-20963-fix-import-on-deleted-entity, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.11569149,"height":0.025538707},"on_screen":true,"help_text":"Pull request #12121 exists for current branch JY-20963-fix-import-on-deleted-entity","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8374335,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"bounds":{"left":0.85272604,"top":0.019952115,"width":0.062832445,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12","depth":4,"bounds":{"left":0.37865692,"top":0.15003991,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"9","depth":4,"bounds":{"left":0.39029256,"top":0.15003991,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.39993352,"top":0.14844373,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.40724733,"top":0.14844373,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Hubspot\\Journal;\n\nuse Illuminate\\Support\\Facades\\Log;\nuse Illuminate\\Support\\Facades\\Redis;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Repositories\\Crm\\CrmConfigurationRepository;\nuse Jiminny\\Repositories\\TeamRepository;\nuse Jiminny\\Services\\Crm\\Hubspot\\Webhook\\WebhookEventProcessor;\n\nclass HubspotJournalPollingService\n{\n private const string OFFSET_CACHE_KEY = 'hubspot_journal_offset';\n private const string POLLING_LOCK_KEY = 'hubspot_journal_polling_lock';\n private const string STOP_FLAG_KEY = 'hubspot_journal_stop_flag';\n private const int LOCK_TTL_SECONDS = 120; // 2 minutes - renewed every 30 seconds\n private const int LOCK_RENEWAL_INTERVAL = 30; // Renew lock every 30 seconds\n private const int BASE_SLEEP_SECONDS = 5; // Base sleep when no data\n private const int MAX_SLEEP_SECONDS = 120; // Maximum sleep duration\n private const int EMPTY_THRESHOLD_FOR_BACKOFF = 3; // Empty results before increasing sleep\n private const int MAX_CYCLES_DEFAULT = 3000; // Default maximum cycles before stopping\n private const int MEMORY_CRITICAL_THRESHOLD = 90; // 90% of memory limit\n private const int MAX_BACKOFF_SECONDS = 300;\n private const int MAX_OFFSET_RETRIES = 3;\n private const int MAX_RUNTIME_SECONDS = 240; // 4 minutes\n private const int MAX_EMPTY_RESULTS_BEFORE_EXIT = 5;\n private const int LOG_INTERVAL_CYCLES = 10;\n\n private bool $shouldStop = false;\n private int $consecutiveEmptyResults = 0;\n private array $offsetRetryCount = [];\n\n private int $cycleCount = 0;\n private int $startTime = 0;\n private int $lastLockRenewal = 0;\n\n private float $totalApiTime = 0;\n private float $totalDownloadTime = 0;\n private float $totalTransformTime = 0;\n private float $totalProcessTime = 0;\n\n private int $totalJournalFilesDownloaded = 0;\n private int $totalEventsProcessed = 0;\n private int $emptyJournalFiles = 0;\n private int $otherPortalSkipped = 0;\n\n public function __construct(\n private HubspotJournalApiClient $apiClient,\n private JournalEventTransformer $transformer,\n private WebhookEventProcessor $eventProcessor\n ) {\n }\n\n /**\n * Start continuous polling of the HubSpot journal\n */\n public function startPolling(): void\n {\n $this->startTime = time();\n $this->cycleCount = 0;\n $this->logPollingStart();\n\n if (! $this->acquirePollingLock()) {\n Log::warning('[HubSpot Journal Polling] Another polling process is already running');\n\n return;\n }\n\n try {\n while ($this->shouldContinuePolling()) {\n $this->cycleCount++;\n $this->executePollingCycle();\n }\n } catch (\\Throwable $e) {\n Log::error('[HubSpot Journal Polling] Error while polling', [\n 'error' => $e->getMessage(),\n 'trace' => $e->getTraceAsString(),\n ]);\n } finally {\n $this->cleanupPollingSession();\n }\n }\n\n /**\n * Perform a single polling cycle\n * Returns true if work was found and processed, false if no work available, null if entry was skipped\n */\n public function pollOnce(): ?bool\n {\n $currentOffset = $this->getCurrentOffset();\n\n $apiStart = microtime(true);\n $apiResult = $currentOffset === null\n ? $this->apiClient->getLatestJournalEntry()\n : $this->apiClient->getNextJournalEntry($currentOffset);\n $this->totalApiTime += (microtime(true) - $apiStart) * 1000;\n\n if (! $apiResult->success) {\n return $this->handleApiResult($apiResult, $currentOffset ?? 'latest');\n }\n\n if ($apiResult->data === null) {\n Log::info('[HubSpot Journal Polling] No data');\n\n return false;\n }\n\n $offset = $apiResult->data['currentOffset'];\n $s3Url = $apiResult->data['url'];\n $retryCount = $this->offsetRetryCount[$offset] ?? 0;\n\n $downloadStart = microtime(true);\n $downloadResult = $this->apiClient->downloadJournalFile($s3Url);\n $this->totalDownloadTime += (microtime(true) - $downloadStart) * 1000;\n\n if (! $downloadResult->success) {\n return $this->handleDownloadResult($downloadResult, $offset, $retryCount);\n }\n\n $this->totalJournalFilesDownloaded++;\n $journalData = $downloadResult->data;\n\n $transformStart = microtime(true);\n\n try {\n $transformedEvents = $this->transformer->transformJournalEvents($journalData);\n } catch (\\Exception $e) {\n return $this->handleTransformationFailure($offset, $retryCount, $e);\n }\n $this->totalTransformTime += (microtime(true) - $transformStart) * 1000;\n unset($journalData);\n\n $processStart = microtime(true);\n $eventsCount = count($transformedEvents);\n $this->totalEventsProcessed += $eventsCount;\n\n if ($eventsCount === 0) {\n $this->emptyJournalFiles++;\n } else {\n $this->eventProcessor->processEvents($transformedEvents, '[HubSpot Journal Polling]');\n }\n $this->totalProcessTime += (microtime(true) - $processStart) * 1000;\n\n $this->updateOffset($offset);\n unset($transformedEvents);\n\n $this->logProgressIfNeeded();\n\n return $eventsCount > 0;\n }\n\n private function logProgressIfNeeded(): void\n {\n if ($this->cycleCount === 0 || $this->cycleCount % self::LOG_INTERVAL_CYCLES !== 0) {\n return;\n }\n\n $cycles = $this->cycleCount;\n $avgTotal = ($this->totalApiTime + $this->totalDownloadTime + $this->totalTransformTime + $this->totalProcessTime) / $cycles;\n\n Log::info('[HubSpot Journal Polling] Progress', [\n 'cycles' => $cycles,\n 'files' => $this->totalJournalFilesDownloaded,\n 'events' => $this->totalEventsProcessed,\n 'empty_files' => $this->emptyJournalFiles,\n 'avg_ms' => round($avgTotal, 1),\n 'avg_api_ms' => round($this->totalApiTime / $cycles, 1),\n 'avg_download_ms' => round($this->totalDownloadTime / $cycles, 1),\n 'avg_transform_ms' => round($this->totalTransformTime / $cycles, 1),\n 'avg_process_ms' => round($this->totalProcessTime / $cycles, 1),\n ]);\n }\n\n /**\n * Get the current polling offset from Redis\n */\n private function getCurrentOffset(bool $cacheOnly = false): ?string\n {\n $offset = Redis::get(self::OFFSET_CACHE_KEY);\n\n if (! $offset && ! $cacheOnly) {\n $offset = $this->getDbOffset();\n }\n\n return $offset ? (string) $offset : null;\n }\n\n /**\n * Get the last stored offset from the database\n */\n public function getDbOffset(): ?string\n {\n $jiminnyTeam = $this->getJiminnyTeam();\n\n if (! $jiminnyTeam instanceof Team) {\n Log::error('[HubSpot Journal Polling] Jiminny team not found');\n\n return null;\n }\n\n $crmRepository = app(CrmConfigurationRepository::class);\n\n $offset = $crmRepository->getSetting($jiminnyTeam->getCrmConfiguration(), 'hubspot_journal_offset');\n\n Log::info('[HubSpot Journal Polling] Getting offset from database', [\n 'offset' => $offset,\n 'jiminny_team_id' => $jiminnyTeam->getId(),\n ]);\n\n return $offset;\n }\n\n /**\n * Reset the database offset\n */\n public function resetDbOffset(): void\n {\n $jiminnyTeam = $this->getJiminnyTeam();\n\n if (! $jiminnyTeam instanceof Team) {\n Log::error('[HubSpot Journal Polling] Jiminny team not found');\n\n return;\n }\n\n $crmRepository = app(CrmConfigurationRepository::class);\n\n $crmRepository->updateSetting($jiminnyTeam->getCrmConfiguration(), 'hubspot_journal_offset', '');\n\n Log::info('[HubSpot Journal Polling] Database offset reset');\n }\n\n private function getJiminnyTeam(): ?Team\n {\n $teamRepository = app(TeamRepository::class);\n\n return $teamRepository->getTeamBySlug('jiminny');\n }\n\n private function updateDbOffset(string $offset): void\n {\n $jiminnyTeam = $this->getJiminnyTeam();\n\n if (! $jiminnyTeam instanceof Team) {\n Log::error('[HubSpot Journal Polling] Jiminny team not found');\n\n return;\n }\n\n $crmRepository = app(CrmConfigurationRepository::class);\n\n $crmRepository->updateSetting($jiminnyTeam->getCrmConfiguration(), 'hubspot_journal_offset', $offset);\n }\n\n /**\n * Update the polling offset\n */\n private function updateOffset(string $offset): void\n {\n Redis::setex(self::OFFSET_CACHE_KEY, 259200, $offset); // 3 days TTL\n $this->clearOffsetRetryCount($offset);\n }\n\n /**\n * Reset the polling offset\n */\n public function resetOffset(): void\n {\n Redis::del(self::OFFSET_CACHE_KEY);\n Log::info('[HubSpot Journal Polling] Reset polling offset');\n }\n\n /**\n * Set a specific offset (for manual override or recovery)\n */\n public function setOffset(string $offset): void\n {\n $this->updateOffset($offset);\n\n Log::warning('[HubSpot Journal Polling] Offset manually set', [\n 'offset' => $offset,\n ]);\n }\n\n /**\n * Get current polling status\n */\n public function getPollingStatus(): array\n {\n $lockDataJson = Redis::get(self::POLLING_LOCK_KEY);\n $lockData = $lockDataJson ? json_decode($lockDataJson, true) : null;\n\n return [\n 'is_locked' => $lockData !== null,\n 'current_offset' => $this->getCurrentOffset(),\n 'lock_expires_at' => $lockData['expires_at'] ?? null,\n 'lock_acquired_at' => $lockData['acquired_at'] ?? null,\n ];\n }\n\n /**\n * Acquire exclusive polling lock to prevent multiple instances\n */\n private function acquirePollingLock(): bool\n {\n $expiresAt = now()->addSeconds(self::LOCK_TTL_SECONDS)->toISOString();\n\n // Use atomic operation to set both lock and expiration data\n $lockData = [\n 'locked' => true,\n 'expires_at' => $expiresAt,\n 'acquired_at' => now()->toISOString(),\n ];\n\n // Use SETNX (SET if Not eXists) for atomic lock acquisition\n $lockAcquired = Redis::set(self::POLLING_LOCK_KEY, json_encode($lockData), 'EX', self::LOCK_TTL_SECONDS, 'NX');\n\n if ($lockAcquired) {\n $this->lastLockRenewal = time();\n Log::info('[HubSpot Journal Polling] Acquired polling lock', [\n 'expires_at' => $expiresAt,\n ]);\n }\n\n return (bool) $lockAcquired;\n }\n\n /**\n * Release the polling lock\n */\n private function releasePollingLock(): void\n {\n Redis::del(self::POLLING_LOCK_KEY);\n Log::info('[HubSpot Journal Polling] Released polling lock');\n }\n\n /**\n * Force release the polling lock (for emergency situations)\n */\n public function forceReleaseLock(): void\n {\n $this->releasePollingLock();\n Log::warning('[HubSpot Journal Polling] Force released polling lock');\n }\n\n /**\n * Signal the polling service to stop gracefully\n */\n public function requestStop(): void\n {\n Redis::setex(self::STOP_FLAG_KEY, 300, '1'); // 5 minutes TTL\n $this->shouldStop = true;\n Log::info('[HubSpot Journal Polling] Stop requested');\n }\n\n /**\n * Check if polling should stop\n */\n private function shouldStop(): bool\n {\n // Check local flag first (faster)\n if ($this->shouldStop) {\n return true;\n }\n\n // Check Redis flag (for external stop requests)\n if (Redis::exists(self::STOP_FLAG_KEY)) {\n $this->shouldStop = true;\n\n return true;\n }\n\n return false;\n }\n\n /**\n * Clear the stop flag and reset state to allow service to start\n */\n public function clearStopFlag(): void\n {\n Redis::del(self::STOP_FLAG_KEY);\n $this->shouldStop = false;\n $this->resetPollingState();\n\n Log::info('[HubSpot Journal Polling] Stop flag cleared and state reset');\n }\n\n /**\n * Reset polling state without clearing stop flag\n */\n private function resetPollingState(): void\n {\n $this->consecutiveEmptyResults = 0;\n $this->cycleCount = 0;\n $this->startTime = 0;\n $this->totalApiTime = 0;\n $this->totalDownloadTime = 0;\n $this->totalTransformTime = 0;\n $this->totalProcessTime = 0;\n $this->totalJournalFilesDownloaded = 0;\n $this->totalEventsProcessed = 0;\n $this->emptyJournalFiles = 0;\n $this->otherPortalSkipped = 0;\n }\n\n public function hasStopFlag(): bool\n {\n return (bool) Redis::exists(self::STOP_FLAG_KEY);\n }\n\n /**\n * Calculate adaptive sleep duration based on consecutive empty results\n */\n private function calculateAdaptiveSleep(): int\n {\n if ($this->consecutiveEmptyResults < self::EMPTY_THRESHOLD_FOR_BACKOFF) {\n return self::BASE_SLEEP_SECONDS; // 5 second\n }\n\n // Progressive backoff: 15s -> 30s -> 60s -> 120s (max)\n $delay = 3 * self::BASE_SLEEP_SECONDS;\n $sleepDuration = $delay * (2 ** ($this->consecutiveEmptyResults - self::EMPTY_THRESHOLD_FOR_BACKOFF));\n\n return min($sleepDuration, self::MAX_SLEEP_SECONDS);\n }\n\n private function logPollingStart(): void\n {\n Log::info('[HubSpot Journal Polling] Service starting', [\n 'memory_limit' => ini_get('memory_limit'),\n 'max_execution_time' => ini_get('max_execution_time'),\n 'initial_memory_mb' => round(memory_get_usage(true) / 1024 / 1024, 2),\n ]);\n }\n\n /**\n * Log polling service end information\n */\n private function logPollingEnd(): void\n {\n $runtime = time() - $this->startTime;\n $cycles = max($this->cycleCount, 1);\n\n Log::info('[HubSpot Journal Polling] Service ending', [\n 'runtime_seconds' => $runtime,\n 'total_cycles' => $this->cycleCount,\n 'files_downloaded' => $this->totalJournalFilesDownloaded,\n 'empty_files' => $this->emptyJournalFiles,\n 'other_portal_skipped' => $this->otherPortalSkipped,\n 'total_events' => $this->totalEventsProcessed,\n 'events_per_file' => $this->totalJournalFilesDownloaded > 0\n ? round($this->totalEventsProcessed / $this->totalJournalFilesDownloaded, 1)\n : 0,\n 'avg_api_ms' => round($this->totalApiTime / $cycles, 1),\n 'avg_download_ms' => round($this->totalDownloadTime / $cycles, 1),\n 'avg_transform_ms' => round($this->totalTransformTime / $cycles, 1),\n 'avg_process_ms' => round($this->totalProcessTime / $cycles, 1),\n 'peak_memory_mb' => round(memory_get_peak_usage(true) / 1024 / 1024, 2),\n ]);\n }\n\n /**\n * Improved stop condition check with clear reasoning\n */\n private function shouldContinuePolling(): bool\n {\n // Check explicit stop request first (fastest check)\n if ($this->shouldStop()) {\n Log::info('[HubSpot Journal Polling] Stop requested, ending polling');\n\n return false;\n }\n\n if ($this->consecutiveEmptyResults >= self::MAX_EMPTY_RESULTS_BEFORE_EXIT) {\n Log::warning('[HubSpot Journal Polling] Maximum empty results reached, stopping', [\n 'empty_results' => $this->consecutiveEmptyResults,\n 'max_empty_results' => self::MAX_EMPTY_RESULTS_BEFORE_EXIT,\n ]);\n\n return false;\n }\n\n // Check runtime limit (4 minutes)\n $runtime = time() - $this->startTime;\n if ($runtime >= self::MAX_RUNTIME_SECONDS) {\n Log::warning('[HubSpot Journal Polling] Maximum runtime reached, stopping', [\n 'runtime_seconds' => $runtime,\n 'runtime_minutes' => round($runtime / 60, 1),\n 'max_runtime_seconds' => self::MAX_RUNTIME_SECONDS,\n ]);\n\n return false;\n }\n\n // Check memory limits (prevent OOM)\n $currentMemory = memory_get_usage(true);\n $memoryLimitBytes = $this->parseMemoryLimit(ini_get('memory_limit'));\n\n if ($memoryLimitBytes > 0 && $currentMemory > ($memoryLimitBytes * self::MEMORY_CRITICAL_THRESHOLD / 100)) {\n Log::warning('[HubSpot Journal Polling] Memory limit approaching, stopping', [\n 'current_memory_mb' => round($currentMemory / 1024 / 1024, 2),\n 'memory_limit' => ini_get('memory_limit'),\n 'usage_percent' => round(($currentMemory / $memoryLimitBytes) * 100, 1),\n ]);\n\n return false;\n }\n\n // Check for excessive cycles (prevent runaway processes)\n if ($this->cycleCount > self::MAX_CYCLES_DEFAULT) {\n Log::warning('[HubSpot Journal Polling] Maximum cycles reached, stopping', [\n 'cycles' => $this->cycleCount,\n 'max_cycles' => self::MAX_CYCLES_DEFAULT,\n ]);\n\n return false;\n }\n\n return true;\n }\n\n /**\n * Handle when work is found - reset counters and continue immediately\n */\n private function handleWorkFound(): void\n {\n $this->consecutiveEmptyResults = 0;\n }\n\n /**\n * Handle when no work is found - implement adaptive sleep\n */\n private function handleNoWorkFound(): void\n {\n $this->consecutiveEmptyResults++;\n $sleepDuration = $this->calculateAdaptiveSleep();\n\n Log::debug('[HubSpot Journal Polling] No work found, sleeping', [\n 'consecutive_empty' => $this->consecutiveEmptyResults,\n 'sleep_seconds' => $sleepDuration,\n 'cycle' => $this->cycleCount,\n ]);\n\n $this->responsiveSleep($sleepDuration);\n }\n\n /**\n * Sleep with responsive stop checking\n */\n private function responsiveSleep(int $seconds): void\n {\n for ($i = 0; $i < $seconds && $this->shouldContinuePolling(); $i++) {\n sleep(1);\n }\n }\n\n /**\n * Parse memory limit string to bytes\n */\n private function parseMemoryLimit(string $memoryLimit): int\n {\n if ($memoryLimit === '-1') {\n return 0; // Unlimited\n }\n\n $unit = strtolower(substr($memoryLimit, -1));\n $value = (int) substr($memoryLimit, 0, -1);\n\n return match ($unit) {\n 'g' => $value * 1024 * 1024 * 1024,\n 'm' => $value * 1024 * 1024,\n 'k' => $value * 1024,\n default => (int) $memoryLimit,\n };\n }\n\n private function executePollingCycle(): void\n {\n $this->renewLockIfNeeded();\n\n $result = $this->pollOnce();\n\n if ($result === true) {\n $this->handleWorkFound();\n } elseif ($result === false) {\n $this->handleNoWorkFound();\n }\n }\n\n private function renewLockIfNeeded(): void\n {\n $now = time();\n if ($now - $this->lastLockRenewal >= self::LOCK_RENEWAL_INTERVAL) {\n $this->renewPollingLock();\n $this->lastLockRenewal = $now;\n }\n }\n\n private function renewPollingLock(): void\n {\n $expiresAt = now()->addSeconds(self::LOCK_TTL_SECONDS)->toISOString();\n\n $lockData = [\n 'locked' => true,\n 'expires_at' => $expiresAt,\n 'acquired_at' => now()->toISOString(),\n 'renewed_at' => now()->toISOString(),\n 'cycle' => $this->cycleCount,\n ];\n\n Redis::setex(self::POLLING_LOCK_KEY, self::LOCK_TTL_SECONDS, json_encode($lockData));\n\n Log::debug('[HubSpot Journal Polling] Lock renewed', [\n 'expires_at' => $expiresAt,\n 'cycle' => $this->cycleCount,\n ]);\n }\n\n private function handleApiResult(JournalApiResult $result, string $context): bool\n {\n if ($result->failureType === JournalApiResult::FAILURE_AUTH) {\n Log::warning('[HubSpot Journal Polling] Auth failure, will retry next cycle', [\n 'context' => $context,\n ]);\n\n return false;\n }\n\n if ($result->failureType === JournalApiResult::FAILURE_RATE_LIMIT) {\n $waitSeconds = min($result->retryAfterSeconds ?? 60, self::MAX_BACKOFF_SECONDS);\n Log::warning('[HubSpot Journal Polling] Rate limit hit, waiting', [\n 'wait_seconds' => $waitSeconds,\n ]);\n $this->responsiveSleep($waitSeconds);\n\n return false;\n }\n\n if ($result->failureType === JournalApiResult::FAILURE_OFFSET_EXPIRED) {\n Log::warning('[HubSpot Journal Polling] Offset expired, resetting to fetch latest data', [\n 'expired_offset' => $context,\n ]);\n $this->resetOffset();\n $this->resetDbOffset();\n\n return false;\n }\n\n if ($result->isPermanentFailure()) {\n Log::error('[HubSpot Journal Polling] Permanent API failure', [\n 'context' => $context,\n 'failure_type' => $result->failureType,\n 'error' => $result->errorMessage,\n ]);\n $this->shouldStop = true;\n\n return false;\n }\n\n Log::warning('[HubSpot Journal Polling] Retryable API failure', [\n 'context' => $context,\n 'failure_type' => $result->failureType,\n 'error' => $result->errorMessage,\n ]);\n\n if ($result->retryAfterSeconds) {\n sleep(min($result->retryAfterSeconds, self::MAX_BACKOFF_SECONDS));\n }\n\n return false;\n }\n\n /**\n * Clean up polling session resources\n */\n private function cleanupPollingSession(): void\n {\n $this->logPollingEnd();\n $this->storeOffsetInDB();\n $this->releasePollingLock();\n $this->apiClient->clearPortalCache();\n $this->resetPollingState();\n }\n\n private function storeOffsetInDB(): void\n {\n // Save current offset to database before cleanup\n $currentOffset = $this->getCurrentOffset(cacheOnly: true);\n if ($currentOffset) {\n $this->updateDbOffset($currentOffset);\n\n Log::info('[HubSpot Journal Polling] Saved offset to database on cleanup', [\n 'offset' => $currentOffset,\n ]);\n }\n }\n\n private function handleDownloadResult(JournalApiResult $result, string $offset, int $retryCount): ?bool\n {\n if ($result->failureType === JournalApiResult::FAILURE_UNKNOWN_PORTAL) {\n $this->otherPortalSkipped++;\n $this->updateOffset($offset);\n\n return null;\n }\n\n if ($result->isPermanentFailure()) {\n Log::warning('[HubSpot Journal Polling] Permanent failure, skipping offset', [\n 'offset' => $offset,\n 'portal_id' => $result->portalId,\n 'failure_type' => $result->failureType,\n 'error' => $result->errorMessage,\n ]);\n $this->updateOffset($offset);\n $this->clearOffsetRetryCount($offset);\n\n return false;\n }\n\n $retryCount++;\n\n if ($retryCount >= self::MAX_OFFSET_RETRIES) {\n Log::error('[HubSpot Journal Polling] Max retries reached, skipping offset', [\n 'offset' => $offset,\n 'portal_id' => $result->portalId,\n 'failure_type' => $result->failureType,\n 'retry_count' => $retryCount,\n ]);\n $this->updateOffset($offset);\n $this->clearOffsetRetryCount($offset);\n\n return false;\n }\n\n Log::warning('[HubSpot Journal Polling] Retryable failure, will retry', [\n 'offset' => $offset,\n 'failure_type' => $result->failureType,\n 'retry_count' => $retryCount,\n 'max_retries' => self::MAX_OFFSET_RETRIES,\n ]);\n\n $this->offsetRetryCount[$offset] = $retryCount;\n\n if ($result->retryAfterSeconds) {\n sleep(min($result->retryAfterSeconds, self::MAX_BACKOFF_SECONDS));\n }\n\n return false;\n }\n\n /**\n * Handle transformation failure with retry logic\n */\n private function handleTransformationFailure(string $offset, int $retryCount, \\Exception $exception): bool\n {\n $retryCount++;\n\n if ($retryCount >= self::MAX_OFFSET_RETRIES) {\n Log::critical('[HubSpot Journal Polling] Max transformation retries reached - SKIPPING offset', [\n 'offset' => $offset,\n 'retry_count' => $retryCount,\n 'error' => $exception->getMessage(),\n 'trace' => $exception->getTraceAsString(),\n ]);\n\n // Skip this offset to prevent infinite loop with corrupted data\n $this->updateOffset($offset);\n $this->clearOffsetRetryCount($offset);\n\n return false;\n }\n\n Log::error('[HubSpot Journal Polling] Transformation failed - will retry', [\n 'offset' => $offset,\n 'retry_count' => $retryCount,\n 'max_retries' => self::MAX_OFFSET_RETRIES,\n 'error' => $exception->getMessage(),\n ]);\n\n $this->offsetRetryCount[$offset] = $retryCount;\n\n return false;\n }\n\n /**\n * Clear retry count for an offset after successful processing\n */\n private function clearOffsetRetryCount(string $offset): void\n {\n unset($this->offsetRetryCount[$offset]);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Hubspot\\Journal;\n\nuse Illuminate\\Support\\Facades\\Log;\nuse Illuminate\\Support\\Facades\\Redis;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Repositories\\Crm\\CrmConfigurationRepository;\nuse Jiminny\\Repositories\\TeamRepository;\nuse Jiminny\\Services\\Crm\\Hubspot\\Webhook\\WebhookEventProcessor;\n\nclass HubspotJournalPollingService\n{\n private const string OFFSET_CACHE_KEY = 'hubspot_journal_offset';\n private const string POLLING_LOCK_KEY = 'hubspot_journal_polling_lock';\n private const string STOP_FLAG_KEY = 'hubspot_journal_stop_flag';\n private const int LOCK_TTL_SECONDS = 120; // 2 minutes - renewed every 30 seconds\n private const int LOCK_RENEWAL_INTERVAL = 30; // Renew lock every 30 seconds\n private const int BASE_SLEEP_SECONDS = 5; // Base sleep when no data\n private const int MAX_SLEEP_SECONDS = 120; // Maximum sleep duration\n private const int EMPTY_THRESHOLD_FOR_BACKOFF = 3; // Empty results before increasing sleep\n private const int MAX_CYCLES_DEFAULT = 3000; // Default maximum cycles before stopping\n private const int MEMORY_CRITICAL_THRESHOLD = 90; // 90% of memory limit\n private const int MAX_BACKOFF_SECONDS = 300;\n private const int MAX_OFFSET_RETRIES = 3;\n private const int MAX_RUNTIME_SECONDS = 240; // 4 minutes\n private const int MAX_EMPTY_RESULTS_BEFORE_EXIT = 5;\n private const int LOG_INTERVAL_CYCLES = 10;\n\n private bool $shouldStop = false;\n private int $consecutiveEmptyResults = 0;\n private array $offsetRetryCount = [];\n\n private int $cycleCount = 0;\n private int $startTime = 0;\n private int $lastLockRenewal = 0;\n\n private float $totalApiTime = 0;\n private float $totalDownloadTime = 0;\n private float $totalTransformTime = 0;\n private float $totalProcessTime = 0;\n\n private int $totalJournalFilesDownloaded = 0;\n private int $totalEventsProcessed = 0;\n private int $emptyJournalFiles = 0;\n private int $otherPortalSkipped = 0;\n\n public function __construct(\n private HubspotJournalApiClient $apiClient,\n private JournalEventTransformer $transformer,\n private WebhookEventProcessor $eventProcessor\n ) {\n }\n\n /**\n * Start continuous polling of the HubSpot journal\n */\n public function startPolling(): void\n {\n $this->startTime = time();\n $this->cycleCount = 0;\n $this->logPollingStart();\n\n if (! $this->acquirePollingLock()) {\n Log::warning('[HubSpot Journal Polling] Another polling process is already running');\n\n return;\n }\n\n try {\n while ($this->shouldContinuePolling()) {\n $this->cycleCount++;\n $this->executePollingCycle();\n }\n } catch (\\Throwable $e) {\n Log::error('[HubSpot Journal Polling] Error while polling', [\n 'error' => $e->getMessage(),\n 'trace' => $e->getTraceAsString(),\n ]);\n } finally {\n $this->cleanupPollingSession();\n }\n }\n\n /**\n * Perform a single polling cycle\n * Returns true if work was found and processed, false if no work available, null if entry was skipped\n */\n public function pollOnce(): ?bool\n {\n $currentOffset = $this->getCurrentOffset();\n\n $apiStart = microtime(true);\n $apiResult = $currentOffset === null\n ? $this->apiClient->getLatestJournalEntry()\n : $this->apiClient->getNextJournalEntry($currentOffset);\n $this->totalApiTime += (microtime(true) - $apiStart) * 1000;\n\n if (! $apiResult->success) {\n return $this->handleApiResult($apiResult, $currentOffset ?? 'latest');\n }\n\n if ($apiResult->data === null) {\n Log::info('[HubSpot Journal Polling] No data');\n\n return false;\n }\n\n $offset = $apiResult->data['currentOffset'];\n $s3Url = $apiResult->data['url'];\n $retryCount = $this->offsetRetryCount[$offset] ?? 0;\n\n $downloadStart = microtime(true);\n $downloadResult = $this->apiClient->downloadJournalFile($s3Url);\n $this->totalDownloadTime += (microtime(true) - $downloadStart) * 1000;\n\n if (! $downloadResult->success) {\n return $this->handleDownloadResult($downloadResult, $offset, $retryCount);\n }\n\n $this->totalJournalFilesDownloaded++;\n $journalData = $downloadResult->data;\n\n $transformStart = microtime(true);\n\n try {\n $transformedEvents = $this->transformer->transformJournalEvents($journalData);\n } catch (\\Exception $e) {\n return $this->handleTransformationFailure($offset, $retryCount, $e);\n }\n $this->totalTransformTime += (microtime(true) - $transformStart) * 1000;\n unset($journalData);\n\n $processStart = microtime(true);\n $eventsCount = count($transformedEvents);\n $this->totalEventsProcessed += $eventsCount;\n\n if ($eventsCount === 0) {\n $this->emptyJournalFiles++;\n } else {\n $this->eventProcessor->processEvents($transformedEvents, '[HubSpot Journal Polling]');\n }\n $this->totalProcessTime += (microtime(true) - $processStart) * 1000;\n\n $this->updateOffset($offset);\n unset($transformedEvents);\n\n $this->logProgressIfNeeded();\n\n return $eventsCount > 0;\n }\n\n private function logProgressIfNeeded(): void\n {\n if ($this->cycleCount === 0 || $this->cycleCount % self::LOG_INTERVAL_CYCLES !== 0) {\n return;\n }\n\n $cycles = $this->cycleCount;\n $avgTotal = ($this->totalApiTime + $this->totalDownloadTime + $this->totalTransformTime + $this->totalProcessTime) / $cycles;\n\n Log::info('[HubSpot Journal Polling] Progress', [\n 'cycles' => $cycles,\n 'files' => $this->totalJournalFilesDownloaded,\n 'events' => $this->totalEventsProcessed,\n 'empty_files' => $this->emptyJournalFiles,\n 'avg_ms' => round($avgTotal, 1),\n 'avg_api_ms' => round($this->totalApiTime / $cycles, 1),\n 'avg_download_ms' => round($this->totalDownloadTime / $cycles, 1),\n 'avg_transform_ms' => round($this->totalTransformTime / $cycles, 1),\n 'avg_process_ms' => round($this->totalProcessTime / $cycles, 1),\n ]);\n }\n\n /**\n * Get the current polling offset from Redis\n */\n private function getCurrentOffset(bool $cacheOnly = false): ?string\n {\n $offset = Redis::get(self::OFFSET_CACHE_KEY);\n\n if (! $offset && ! $cacheOnly) {\n $offset = $this->getDbOffset();\n }\n\n return $offset ? (string) $offset : null;\n }\n\n /**\n * Get the last stored offset from the database\n */\n public function getDbOffset(): ?string\n {\n $jiminnyTeam = $this->getJiminnyTeam();\n\n if (! $jiminnyTeam instanceof Team) {\n Log::error('[HubSpot Journal Polling] Jiminny team not found');\n\n return null;\n }\n\n $crmRepository = app(CrmConfigurationRepository::class);\n\n $offset = $crmRepository->getSetting($jiminnyTeam->getCrmConfiguration(), 'hubspot_journal_offset');\n\n Log::info('[HubSpot Journal Polling] Getting offset from database', [\n 'offset' => $offset,\n 'jiminny_team_id' => $jiminnyTeam->getId(),\n ]);\n\n return $offset;\n }\n\n /**\n * Reset the database offset\n */\n public function resetDbOffset(): void\n {\n $jiminnyTeam = $this->getJiminnyTeam();\n\n if (! $jiminnyTeam instanceof Team) {\n Log::error('[HubSpot Journal Polling] Jiminny team not found');\n\n return;\n }\n\n $crmRepository = app(CrmConfigurationRepository::class);\n\n $crmRepository->updateSetting($jiminnyTeam->getCrmConfiguration(), 'hubspot_journal_offset', '');\n\n Log::info('[HubSpot Journal Polling] Database offset reset');\n }\n\n private function getJiminnyTeam(): ?Team\n {\n $teamRepository = app(TeamRepository::class);\n\n return $teamRepository->getTeamBySlug('jiminny');\n }\n\n private function updateDbOffset(string $offset): void\n {\n $jiminnyTeam = $this->getJiminnyTeam();\n\n if (! $jiminnyTeam instanceof Team) {\n Log::error('[HubSpot Journal Polling] Jiminny team not found');\n\n return;\n }\n\n $crmRepository = app(CrmConfigurationRepository::class);\n\n $crmRepository->updateSetting($jiminnyTeam->getCrmConfiguration(), 'hubspot_journal_offset', $offset);\n }\n\n /**\n * Update the polling offset\n */\n private function updateOffset(string $offset): void\n {\n Redis::setex(self::OFFSET_CACHE_KEY, 259200, $offset); // 3 days TTL\n $this->clearOffsetRetryCount($offset);\n }\n\n /**\n * Reset the polling offset\n */\n public function resetOffset(): void\n {\n Redis::del(self::OFFSET_CACHE_KEY);\n Log::info('[HubSpot Journal Polling] Reset polling offset');\n }\n\n /**\n * Set a specific offset (for manual override or recovery)\n */\n public function setOffset(string $offset): void\n {\n $this->updateOffset($offset);\n\n Log::warning('[HubSpot Journal Polling] Offset manually set', [\n 'offset' => $offset,\n ]);\n }\n\n /**\n * Get current polling status\n */\n public function getPollingStatus(): array\n {\n $lockDataJson = Redis::get(self::POLLING_LOCK_KEY);\n $lockData = $lockDataJson ? json_decode($lockDataJson, true) : null;\n\n return [\n 'is_locked' => $lockData !== null,\n 'current_offset' => $this->getCurrentOffset(),\n 'lock_expires_at' => $lockData['expires_at'] ?? null,\n 'lock_acquired_at' => $lockData['acquired_at'] ?? null,\n ];\n }\n\n /**\n * Acquire exclusive polling lock to prevent multiple instances\n */\n private function acquirePollingLock(): bool\n {\n $expiresAt = now()->addSeconds(self::LOCK_TTL_SECONDS)->toISOString();\n\n // Use atomic operation to set both lock and expiration data\n $lockData = [\n 'locked' => true,\n 'expires_at' => $expiresAt,\n 'acquired_at' => now()->toISOString(),\n ];\n\n // Use SETNX (SET if Not eXists) for atomic lock acquisition\n $lockAcquired = Redis::set(self::POLLING_LOCK_KEY, json_encode($lockData), 'EX', self::LOCK_TTL_SECONDS, 'NX');\n\n if ($lockAcquired) {\n $this->lastLockRenewal = time();\n Log::info('[HubSpot Journal Polling] Acquired polling lock', [\n 'expires_at' => $expiresAt,\n ]);\n }\n\n return (bool) $lockAcquired;\n }\n\n /**\n * Release the polling lock\n */\n private function releasePollingLock(): void\n {\n Redis::del(self::POLLING_LOCK_KEY);\n Log::info('[HubSpot Journal Polling] Released polling lock');\n }\n\n /**\n * Force release the polling lock (for emergency situations)\n */\n public function forceReleaseLock(): void\n {\n $this->releasePollingLock();\n Log::warning('[HubSpot Journal Polling] Force released polling lock');\n }\n\n /**\n * Signal the polling service to stop gracefully\n */\n public function requestStop(): void\n {\n Redis::setex(self::STOP_FLAG_KEY, 300, '1'); // 5 minutes TTL\n $this->shouldStop = true;\n Log::info('[HubSpot Journal Polling] Stop requested');\n }\n\n /**\n * Check if polling should stop\n */\n private function shouldStop(): bool\n {\n // Check local flag first (faster)\n if ($this->shouldStop) {\n return true;\n }\n\n // Check Redis flag (for external stop requests)\n if (Redis::exists(self::STOP_FLAG_KEY)) {\n $this->shouldStop = true;\n\n return true;\n }\n\n return false;\n }\n\n /**\n * Clear the stop flag and reset state to allow service to start\n */\n public function clearStopFlag(): void\n {\n Redis::del(self::STOP_FLAG_KEY);\n $this->shouldStop = false;\n $this->resetPollingState();\n\n Log::info('[HubSpot Journal Polling] Stop flag cleared and state reset');\n }\n\n /**\n * Reset polling state without clearing stop flag\n */\n private function resetPollingState(): void\n {\n $this->consecutiveEmptyResults = 0;\n $this->cycleCount = 0;\n $this->startTime = 0;\n $this->totalApiTime = 0;\n $this->totalDownloadTime = 0;\n $this->totalTransformTime = 0;\n $this->totalProcessTime = 0;\n $this->totalJournalFilesDownloaded = 0;\n $this->totalEventsProcessed = 0;\n $this->emptyJournalFiles = 0;\n $this->otherPortalSkipped = 0;\n }\n\n public function hasStopFlag(): bool\n {\n return (bool) Redis::exists(self::STOP_FLAG_KEY);\n }\n\n /**\n * Calculate adaptive sleep duration based on consecutive empty results\n */\n private function calculateAdaptiveSleep(): int\n {\n if ($this->consecutiveEmptyResults < self::EMPTY_THRESHOLD_FOR_BACKOFF) {\n return self::BASE_SLEEP_SECONDS; // 5 second\n }\n\n // Progressive backoff: 15s -> 30s -> 60s -> 120s (max)\n $delay = 3 * self::BASE_SLEEP_SECONDS;\n $sleepDuration = $delay * (2 ** ($this->consecutiveEmptyResults - self::EMPTY_THRESHOLD_FOR_BACKOFF));\n\n return min($sleepDuration, self::MAX_SLEEP_SECONDS);\n }\n\n private function logPollingStart(): void\n {\n Log::info('[HubSpot Journal Polling] Service starting', [\n 'memory_limit' => ini_get('memory_limit'),\n 'max_execution_time' => ini_get('max_execution_time'),\n 'initial_memory_mb' => round(memory_get_usage(true) / 1024 / 1024, 2),\n ]);\n }\n\n /**\n * Log polling service end information\n */\n private function logPollingEnd(): void\n {\n $runtime = time() - $this->startTime;\n $cycles = max($this->cycleCount, 1);\n\n Log::info('[HubSpot Journal Polling] Service ending', [\n 'runtime_seconds' => $runtime,\n 'total_cycles' => $this->cycleCount,\n 'files_downloaded' => $this->totalJournalFilesDownloaded,\n 'empty_files' => $this->emptyJournalFiles,\n 'other_portal_skipped' => $this->otherPortalSkipped,\n 'total_events' => $this->totalEventsProcessed,\n 'events_per_file' => $this->totalJournalFilesDownloaded > 0\n ? round($this->totalEventsProcessed / $this->totalJournalFilesDownloaded, 1)\n : 0,\n 'avg_api_ms' => round($this->totalApiTime / $cycles, 1),\n 'avg_download_ms' => round($this->totalDownloadTime / $cycles, 1),\n 'avg_transform_ms' => round($this->totalTransformTime / $cycles, 1),\n 'avg_process_ms' => round($this->totalProcessTime / $cycles, 1),\n 'peak_memory_mb' => round(memory_get_peak_usage(true) / 1024 / 1024, 2),\n ]);\n }\n\n /**\n * Improved stop condition check with clear reasoning\n */\n private function shouldContinuePolling(): bool\n {\n // Check explicit stop request first (fastest check)\n if ($this->shouldStop()) {\n Log::info('[HubSpot Journal Polling] Stop requested, ending polling');\n\n return false;\n }\n\n if ($this->consecutiveEmptyResults >= self::MAX_EMPTY_RESULTS_BEFORE_EXIT) {\n Log::warning('[HubSpot Journal Polling] Maximum empty results reached, stopping', [\n 'empty_results' => $this->consecutiveEmptyResults,\n 'max_empty_results' => self::MAX_EMPTY_RESULTS_BEFORE_EXIT,\n ]);\n\n return false;\n }\n\n // Check runtime limit (4 minutes)\n $runtime = time() - $this->startTime;\n if ($runtime >= self::MAX_RUNTIME_SECONDS) {\n Log::warning('[HubSpot Journal Polling] Maximum runtime reached, stopping', [\n 'runtime_seconds' => $runtime,\n 'runtime_minutes' => round($runtime / 60, 1),\n 'max_runtime_seconds' => self::MAX_RUNTIME_SECONDS,\n ]);\n\n return false;\n }\n\n // Check memory limits (prevent OOM)\n $currentMemory = memory_get_usage(true);\n $memoryLimitBytes = $this->parseMemoryLimit(ini_get('memory_limit'));\n\n if ($memoryLimitBytes > 0 && $currentMemory > ($memoryLimitBytes * self::MEMORY_CRITICAL_THRESHOLD / 100)) {\n Log::warning('[HubSpot Journal Polling] Memory limit approaching, stopping', [\n 'current_memory_mb' => round($currentMemory / 1024 / 1024, 2),\n 'memory_limit' => ini_get('memory_limit'),\n 'usage_percent' => round(($currentMemory / $memoryLimitBytes) * 100, 1),\n ]);\n\n return false;\n }\n\n // Check for excessive cycles (prevent runaway processes)\n if ($this->cycleCount > self::MAX_CYCLES_DEFAULT) {\n Log::warning('[HubSpot Journal Polling] Maximum cycles reached, stopping', [\n 'cycles' => $this->cycleCount,\n 'max_cycles' => self::MAX_CYCLES_DEFAULT,\n ]);\n\n return false;\n }\n\n return true;\n }\n\n /**\n * Handle when work is found - reset counters and continue immediately\n */\n private function handleWorkFound(): void\n {\n $this->consecutiveEmptyResults = 0;\n }\n\n /**\n * Handle when no work is found - implement adaptive sleep\n */\n private function handleNoWorkFound(): void\n {\n $this->consecutiveEmptyResults++;\n $sleepDuration = $this->calculateAdaptiveSleep();\n\n Log::debug('[HubSpot Journal Polling] No work found, sleeping', [\n 'consecutive_empty' => $this->consecutiveEmptyResults,\n 'sleep_seconds' => $sleepDuration,\n 'cycle' => $this->cycleCount,\n ]);\n\n $this->responsiveSleep($sleepDuration);\n }\n\n /**\n * Sleep with responsive stop checking\n */\n private function responsiveSleep(int $seconds): void\n {\n for ($i = 0; $i < $seconds && $this->shouldContinuePolling(); $i++) {\n sleep(1);\n }\n }\n\n /**\n * Parse memory limit string to bytes\n */\n private function parseMemoryLimit(string $memoryLimit): int\n {\n if ($memoryLimit === '-1') {\n return 0; // Unlimited\n }\n\n $unit = strtolower(substr($memoryLimit, -1));\n $value = (int) substr($memoryLimit, 0, -1);\n\n return match ($unit) {\n 'g' => $value * 1024 * 1024 * 1024,\n 'm' => $value * 1024 * 1024,\n 'k' => $value * 1024,\n default => (int) $memoryLimit,\n };\n }\n\n private function executePollingCycle(): void\n {\n $this->renewLockIfNeeded();\n\n $result = $this->pollOnce();\n\n if ($result === true) {\n $this->handleWorkFound();\n } elseif ($result === false) {\n $this->handleNoWorkFound();\n }\n }\n\n private function renewLockIfNeeded(): void\n {\n $now = time();\n if ($now - $this->lastLockRenewal >= self::LOCK_RENEWAL_INTERVAL) {\n $this->renewPollingLock();\n $this->lastLockRenewal = $now;\n }\n }\n\n private function renewPollingLock(): void\n {\n $expiresAt = now()->addSeconds(self::LOCK_TTL_SECONDS)->toISOString();\n\n $lockData = [\n 'locked' => true,\n 'expires_at' => $expiresAt,\n 'acquired_at' => now()->toISOString(),\n 'renewed_at' => now()->toISOString(),\n 'cycle' => $this->cycleCount,\n ];\n\n Redis::setex(self::POLLING_LOCK_KEY, self::LOCK_TTL_SECONDS, json_encode($lockData));\n\n Log::debug('[HubSpot Journal Polling] Lock renewed', [\n 'expires_at' => $expiresAt,\n 'cycle' => $this->cycleCount,\n ]);\n }\n\n private function handleApiResult(JournalApiResult $result, string $context): bool\n {\n if ($result->failureType === JournalApiResult::FAILURE_AUTH) {\n Log::warning('[HubSpot Journal Polling] Auth failure, will retry next cycle', [\n 'context' => $context,\n ]);\n\n return false;\n }\n\n if ($result->failureType === JournalApiResult::FAILURE_RATE_LIMIT) {\n $waitSeconds = min($result->retryAfterSeconds ?? 60, self::MAX_BACKOFF_SECONDS);\n Log::warning('[HubSpot Journal Polling] Rate limit hit, waiting', [\n 'wait_seconds' => $waitSeconds,\n ]);\n $this->responsiveSleep($waitSeconds);\n\n return false;\n }\n\n if ($result->failureType === JournalApiResult::FAILURE_OFFSET_EXPIRED) {\n Log::warning('[HubSpot Journal Polling] Offset expired, resetting to fetch latest data', [\n 'expired_offset' => $context,\n ]);\n $this->resetOffset();\n $this->resetDbOffset();\n\n return false;\n }\n\n if ($result->isPermanentFailure()) {\n Log::error('[HubSpot Journal Polling] Permanent API failure', [\n 'context' => $context,\n 'failure_type' => $result->failureType,\n 'error' => $result->errorMessage,\n ]);\n $this->shouldStop = true;\n\n return false;\n }\n\n Log::warning('[HubSpot Journal Polling] Retryable API failure', [\n 'context' => $context,\n 'failure_type' => $result->failureType,\n 'error' => $result->errorMessage,\n ]);\n\n if ($result->retryAfterSeconds) {\n sleep(min($result->retryAfterSeconds, self::MAX_BACKOFF_SECONDS));\n }\n\n return false;\n }\n\n /**\n * Clean up polling session resources\n */\n private function cleanupPollingSession(): void\n {\n $this->logPollingEnd();\n $this->storeOffsetInDB();\n $this->releasePollingLock();\n $this->apiClient->clearPortalCache();\n $this->resetPollingState();\n }\n\n private function storeOffsetInDB(): void\n {\n // Save current offset to database before cleanup\n $currentOffset = $this->getCurrentOffset(cacheOnly: true);\n if ($currentOffset) {\n $this->updateDbOffset($currentOffset);\n\n Log::info('[HubSpot Journal Polling] Saved offset to database on cleanup', [\n 'offset' => $currentOffset,\n ]);\n }\n }\n\n private function handleDownloadResult(JournalApiResult $result, string $offset, int $retryCount): ?bool\n {\n if ($result->failureType === JournalApiResult::FAILURE_UNKNOWN_PORTAL) {\n $this->otherPortalSkipped++;\n $this->updateOffset($offset);\n\n return null;\n }\n\n if ($result->isPermanentFailure()) {\n Log::warning('[HubSpot Journal Polling] Permanent failure, skipping offset', [\n 'offset' => $offset,\n 'portal_id' => $result->portalId,\n 'failure_type' => $result->failureType,\n 'error' => $result->errorMessage,\n ]);\n $this->updateOffset($offset);\n $this->clearOffsetRetryCount($offset);\n\n return false;\n }\n\n $retryCount++;\n\n if ($retryCount >= self::MAX_OFFSET_RETRIES) {\n Log::error('[HubSpot Journal Polling] Max retries reached, skipping offset', [\n 'offset' => $offset,\n 'portal_id' => $result->portalId,\n 'failure_type' => $result->failureType,\n 'retry_count' => $retryCount,\n ]);\n $this->updateOffset($offset);\n $this->clearOffsetRetryCount($offset);\n\n return false;\n }\n\n Log::warning('[HubSpot Journal Polling] Retryable failure, will retry', [\n 'offset' => $offset,\n 'failure_type' => $result->failureType,\n 'retry_count' => $retryCount,\n 'max_retries' => self::MAX_OFFSET_RETRIES,\n ]);\n\n $this->offsetRetryCount[$offset] = $retryCount;\n\n if ($result->retryAfterSeconds) {\n sleep(min($result->retryAfterSeconds, self::MAX_BACKOFF_SECONDS));\n }\n\n return false;\n }\n\n /**\n * Handle transformation failure with retry logic\n */\n private function handleTransformationFailure(string $offset, int $retryCount, \\Exception $exception): bool\n {\n $retryCount++;\n\n if ($retryCount >= self::MAX_OFFSET_RETRIES) {\n Log::critical('[HubSpot Journal Polling] Max transformation retries reached - SKIPPING offset', [\n 'offset' => $offset,\n 'retry_count' => $retryCount,\n 'error' => $exception->getMessage(),\n 'trace' => $exception->getTraceAsString(),\n ]);\n\n // Skip this offset to prevent infinite loop with corrupted data\n $this->updateOffset($offset);\n $this->clearOffsetRetryCount($offset);\n\n return false;\n }\n\n Log::error('[HubSpot Journal Polling] Transformation failed - will retry', [\n 'offset' => $offset,\n 'retry_count' => $retryCount,\n 'max_retries' => self::MAX_OFFSET_RETRIES,\n 'error' => $exception->getMessage(),\n ]);\n\n $this->offsetRetryCount[$offset] = $retryCount;\n\n return false;\n }\n\n /**\n * Clear retry count for an offset after successful processing\n */\n private function clearOffsetRetryCount(string $offset): void\n {\n unset($this->offsetRetryCount[$offset]);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"bounds":{"left":0.41589096,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"bounds":{"left":0.4245346,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"bounds":{"left":0.43550533,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"bounds":{"left":0.44414893,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"bounds":{"left":0.45279256,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"bounds":{"left":0.4637633,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"bounds":{"left":0.47473404,"top":0.09896249,"width":0.024268618,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"bounds":{"left":0.5013298,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"bounds":{"left":0.51230055,"top":0.09896249,"width":0.029587766,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny","depth":4,"bounds":{"left":0.7237367,"top":0.09896249,"width":0.02825798,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"45","depth":4,"bounds":{"left":0.6938165,"top":0.123703115,"width":0.010305851,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.70611703,"top":0.123703115,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"41","depth":4,"bounds":{"left":0.71542555,"top":0.123703115,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"66","depth":4,"bounds":{"left":0.72706115,"top":0.123703115,"width":0.010305851,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.7390292,"top":0.12210695,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7463431,"top":0.12210695,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993\nSELECT * FROM users WHERE id = 25061;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 994;\nSELECT * FROM crm_profiles WHERE user_id = 25061;\n\nselect * from crm_configurations where id = 834;\nSELECT * FROM teams WHERE id = 882;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;\n\nSELECT * FROM contacts where crm_configuration_id = 834;\nSELECT * FROM opportunities WHERE team_id = 933\n# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');\nAND id IN (8482561,18352941,19042734,19232139,19445140,19472541);\nSELECT * FROM opportunity_contacts\nWHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 485; #\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nselect crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id\nwhere crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')\n# and l.converted_at IS NOT NULL\n;\n\n# ********************************************************************\nSELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')\nand opportunity_id IS NULL\norder by id desc;\n\nSELECT * FROM teams WHERE id = 604; # 598\nSELECT * FROM activities WHERE id = 74410828; # chelseaw@allvoices.co\nSELECT * FROM accounts WHERE id = 20068382;\nSELECT * FROM accounts WHERE id = 35186038;\n\nSELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 559 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;\nselect * from sidekick_settings where team_id = 781;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100\n\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 711;\nSELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL\nand is_internal = 0 and status = 'completed'\norder by id desc;\n\nSELECT * FROM crm_layout_entities\nWHERE crm_layout_id IN (2352, 2353);\n;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 556 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;\nSELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;\nselect * from contacts\nwhere crm_configuration_id = 530\nand crm_provider_id = 872252;\n\nselect * from activities where crm_configuration_id = 530\nand user_id = 14343 and type like '%softphone%'\nand created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);\n\n\nSELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t\nJOIN crm_configurations c ON t.id = c.team_id\nWHERE t.status = 'active';\n\nSELECT * FROM teams where id = 1091;\nSELECT * FROM crm_configurations where team_id = 1091;\nSELECT * FROM activity_providers where team_id = 1091;\nSELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT * FROM teams WHERE name LIKE '%Leadventure%';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1091 and sa.provider = 'salesforce';\n\nSELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812\nSELECT * FROM teams where id = 862;\nSELECT * FROM crm_configurations where team_id = 862;\nSELECT * FROM activity_providers where team_id = 862;\nSELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT t.id, crm.id, crm.provider, ap.* FROM teams t\njoin crm_configurations crm on t.id = crm.team_id\njoin activity_providers ap on t.id = ap.team_id\nwhere t.status = 'active' and ap.is_enabled = 1\nand crm.provider = 'hubspot'\nand ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',\n 'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');\n\nSELECT * FROM teams where id = 1068;\nSELECT * FROM crm_configurations where team_id = 1068;\nSELECT * FROM activity_providers where team_id = 1068;\n\nSELECT * FROM activities a\nwhere crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')\nand a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'\n )\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by a.id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1068 and sa.provider = 'hubspot';\n\n# ********************************************************************\n# ********************************************************************\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262\nSELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\nselect * from crm_layouts where crm_configuration_id = 834;\nselect * from crm_layout_entities where crm_layout_id = 2780;\nselect * from crm_fields where id IN (321153,321192,321193,321194);\n\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1057 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8\n\nSELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20\n\nSELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10\n\nSELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #\n\nSELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;\nselect * from users where team_id = 51; # 7783\nSELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130\nselect * from activity_searches where user_id = 7783;\nselect * from activity_search_filters where activity_search_id IN (32291, 32292);\n\nSELECT asf.activity_search_id, asf.id, asf.value\nFROM activity_search_filters asf\nWHERE asf.filter = 'group_id'\nAND asf.value IN (\n SELECT CONCAT(\n HEX(SUBSTR(uuid, 5, 4)), '-',\n HEX(SUBSTR(uuid, 3, 2)), '-',\n HEX(SUBSTR(uuid, 1, 2)), '-',\n HEX(SUBSTR(uuid, 9, 2)), '-',\n HEX(SUBSTR(uuid, 11))\n )\n FROM groups\n WHERE deleted_at IS NOT NULL\n);\n\nSELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th\n# ********************************************************************\nSELECT * FROM crm_configurations where provider = 'hubspot';\nSELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133\nSELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null\n# ********************************************************************\n\nselect * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';\nselect\n cp.*\n# DISTINCT t.id\n# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields\nFROM crm_profiles cp\nJOIN crm_configurations crm on crm.id = cp.crm_configuration_id\nJOIN users u on u.id = cp.user_id\nJOIN teams t ON t.id = crm.team_id\nWHERE crm.provider = 'salesforce' and t.status = 'active'\n and cp.archived_at IS NULL and u.deleted_at IS NULL\n and t.id NOT IN (1093)\n and t.id = 2\n and cp.contact_fields IS NULL;\n# and c.crm_provider_id = '003Uu00000ojD4NIAU';\n\nSELECT * FROM users WHERE id = 26484;\nSELECT * FROM crm_profiles WHERE user_id = 26484;\nSELECT * FROM social_accounts WHERE sociable_id = 26484;\nSELECT * FROM crm_configurations where provider = 'salesforce';\nselect * from users where id IN (10022, 10403);\nselect * from users where team_id IN (526);\nselect * from teams where id IN (526, 532);\nselect * from crm_configurations where id IN (500, 516);\nselect * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);\nselect * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 526 and sa.provider = 'salesforce';\nselect * from team_settings where team_id IN (526, 532);\n\nselect * from users where id IN (22824);\nselect * from crm_profiles where crm_configuration_id IN (1026);\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1093 and sa.provider = 'salesforce';\n\nselect * from teams where id = 1099;\nselect * from users where id = 29643\n\nselect * from activity_processing_states;\n\nSELECT * FROM teams where name LIKE '%Fare%'; # 233\nSELECT * FROM opportunities where crm_configuration_id = 215\n# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'\n;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1088 and sa.provider = 'hubspot';\n\nSELECT * FROM teams order by updated_at DESC\nSELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account\n\nselect * from crm_configurations where provider = 'pipedrive';\n\nselect * from teams where id = 957;\nselect * from crm_configurations where id = 957;\n\nSELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743\nSELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;\n\nselect * from users where team_id = 1; # 26726 - Gabriela Dureva\nSELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific\nselect * from activities where user_id = 26726 order by id desc;\nselect * from contacts where crm_configuration_id = 1\nand email IN ('charlotte.ward@prolific.com', 'frankie.bryant@prolific.com'); # 2094416, 2093620\nSELECT * FROM contacts WHERE id = 6284931;\n\nSELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id\nWHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;\n\nselect * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);\nselect * from crm_configurations where id = 1;\n\n43801692-1aeb-32ce-acba-5b80a479701a\n44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b\n405975c0-b3d0-7aaa-821f-09d59cae6dd1\n4caf848d-4bed-2299-b248-7788d41f9fca\n49bedc3f-f196-eef3-89c3-dea6a3b4aa63\n43420989-a09d-b8f8-9806-c8bbf7a02aac\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nSELECT * FROM activities WHERE id = 75461988;\n\nSELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;\n\nselect * from contacts where id = 17900517;\n\nselect * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id\nwhere crm.provider != 'salesforce';\n\nselect * from users where id = 21047;\nSELECT * FROM crm_configurations WHERE id = 892;\nSELECT * FROM teams WHERE id = 942;\nselect * from opportunities where team_id = 942 order by updated_at desc;\nselect * from contacts where team_id = 942 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 942 and sa.provider = 'hubspot';\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430\nSELECT * FROM crm_configurations WHERE id = 1;\nSELECT * FROM teams WHERE crm_id = 1;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nselect id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1\nSELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430\n\nselect * from teams where id = 852;\nselect * from groups where id = 2286;\nselect * from sidekick_settings where team_id = 852;\nselect * from default_activity_types where team_id = 852;\n\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1 AND u.deleted_at IS NULL\nAND u.crm_required = 1\nAND u.team_id = 1\nORDER BY u.team_id;\n\nSELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (\n18481\n );\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1\n AND u.deleted_at IS NULL\n AND u.crm_required = 1\n# AND u.team_id = 1\n AND p.id IS NULL -- Move this condition to WHERE clause\nORDER BY u.team_id;\n\nSELECT * FROM opportunities WHERE id = 20002609;\nselect * from teams where id = 1122; # Velatir, 29953 - christian@velatir.com\nselect * from crm_configurations where id = 1060;\nselect * from crm_layouts where crm_configuration_id = 1060;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1122 and sa.provider = 'hubspot';\nselect * from opportunities where team_id = 1122 order by updated_at desc;\n\nselect * from crm_field_data where object_type = 'contact';\n\nSELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 248 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS\nSELECT * FROM users where id = 24115;\nSELECT * FROM accounts where id = 4002896;\nSELECT * FROM teams WHERE name LIKE '%adswerve%';\nSELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN (\"0069N000003GIQ9QAO\",\"0061r000019yGP9AAM\",\"0066900001S2KWlAAN\",\"0066900001TDpj2AAD\",\"0066900001b8uEwAAI\",\"0069N000001rQi0QAE\",\"006QF00000KD40mYAD\",\"006QF00000LzpRJYAZ\",\"0069N000002uomtQAA\",\"0069N000002xlMLQAY\",\"0066900001NV6ubAAD\",\"0061r00001HJp45AAD\",\"006QF00000uTlUoYAK\",\"006QF00000v0bZqYAI\");\nSELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203\n\nSELECT u.id, u.email, ac.name, a.* FROM activities a\nJOIN users u ON a.user_id = u.id\nJOIN accounts ac ON a.account_id = ac.id\nWHERE\nuuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or\nuuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or\nuuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;\n\nselect * from users where id = 5825;\nSELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;\n\nselect * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;\n19594, 862\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 862 and sa.provider = 'salesforce';\n\nselect * from automated_reports where id = 36;\nselect ar.frequency, r.*, ar.* from automated_report_results r\njoin automated_reports ar on r.report_id = ar.id\nwhere ar.frequency != 'one_off';\n\nselect s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;\nselect * from nudges n where n.activity_search_id\n\nselect * from teams where created_at > '2026-03-09';\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;\n\nselect * from users where team_id = 1 and name like '%Lukas%'; # 7160\n\nSELECT * FROM teams WHERE id = 575;\nselect * from opportunities where team_id = 575;\nSELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,\nselect * from opportunities where team_id = 1126;\nSELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,\nselect * from opportunities where team_id = 1125;\nselect * from contacts c\nwhere c.team_id = 882;\n\nSELECT * FROM activities WHERE id = 76822967;\nSELECT * FROM crm_profiles WHERE user_id = 15440;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 555;\nSELECT * FROM crm_configurations WHERE id = 555;\nSELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 581 and sa.provider = 'salesforce';\n\nSELECT * FROM automated_report_results order by id desc;\n\nselect * from features;\nselect * from team_features where feature_id = 40;\n\nselect * from teams where id = 556;\n\nselect * from automated_reports;\nwhere id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , [\"pdf\",\"podcast\"]\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\nselect * from automated_report_results order by id desc;\nSELECT * FROM automated_report_results WHERE id = 1919;\n\nselect * from automated_report_results WHERE report_id = 54;\n\nselect * from opportunities where id = 7594349;\n\nSELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - jiminnyintegration@lesmills.com\nselect * from playbooks where team_id = 711; # event 226147\nSELECT * FROM playbook_categories WHERE playbook_id = 5515;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';\nSELECT * FROM crm_fields WHERE id = 226147;\nSELECT * FROM crm_field_values WHERE crm_field_id = 226147;\n\nSELECT * FROM crm_configurations WHERE id = 692;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 711 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;\n\nselect * from leads;\n\nselect * from calendars;\n\nSELECT\n t.id AS team_id,\n t.name,\n LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain\nFROM teams t\nJOIN users u ON u.team_id = t.id\nJOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'\nLEFT JOIN team_domains td\n ON td.team_id = t.id\n AND td.deleted_at IS NULL\n AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))\nGROUP BY t.id, t.name, calendar_domain\nORDER BY t.name, calendar_domain;\n\nselect * from users u join calendars c on c.user_id = u.id\nwhere u.team_id = 882;\n\n\nselect * from activities where id = 74049485; # team 563 crm 537\nselect * from activities where id = 73272382; # team 563 crm 537\nselect * from activities where id = 64400389; # team 563 crm 537\nselect * from activities where id = 58081273; # team 563 crm 537\nselect * from activities where id = 54520297; # team 563 crm 537\nselect * from participants where activity_id = 58081273;\n\nselect * from activities where crm_configuration_id = 537 and provider = 'aircall'\nand account_id = 19003658 order by updated_at desc;\n\nselect * from contacts where crm_configuration_id = 537 and id = 35957759;\nselect * from accounts where crm_configuration_id = 537 and id = 19003658;\n\nselect * from automated_report_results where id = 1976;\nselect * from automated_reports where id = 583;\nselect * from activity_searches where id = 87714;\nselect * from activity_search_filters where activity_search_id = 87714;\n\nSELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid\nor uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot';\nselect * from rate_limits;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2\nand id IN (18, 1872);\nselect * from automated_reports where id = 54;\nSELECT * FROM users WHERE id IN (24623,29443,29613);\n\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\n\nselect * from text_relays where created_at > '2026-05-01';\nand id IN (32415, 32416);\n# and id = 32412;\n\nselect * from users where team_id = 2 and email like '%scott%' and id = 29510;\n\nSELECT * FROM activities WHERE uuid_to_bin('67cebfc2-ed56-44a2-8c68-7a0286ed8618') = uuid; # 79763436\n\nSELECT email_provider_id, COUNT(*) as count, GROUP_CONCAT(id) as ids, GROUP_CONCAT(status) as statuses\nFROM text_relays\nWHERE email_provider_id IN ('19e2027868a64b42', '19e2033ed8ea6b10')\nGROUP BY email_provider_id;\nSELECT id, status, telephony_provider_id, created_at\nFROM activities\nWHERE id IN (80028719, 80028846);\nSELECT id, status, code, email_sent_at, created_at, updated_at\nFROM text_relays\nWHERE id IN (32415, 32416);\nSELECT id, status, code, sender, recipient, created_at\nFROM text_relays\nWHERE sender LIKE '%mario.georgiev%' OR sender LIKE '%stoyan.tomov%'\nORDER BY created_at DESC\nLIMIT 10;\n\nSELECT id, uuid, status, code, sender, recipient, created_at, updated_at\nFROM text_relays\nWHERE uuid = uuid_to_bin('0626141c-27a6-4d8c-aff8-7c8020a2c656');\n\n# ***************\nSELECT DISTINCT u.id, u.email, u.name, u.softphone_number, COUNT(a.id) as sms_count\nFROM users u\nINNER JOIN activities a ON u.id = .user_id\nWHERE a.type LIKE 'sms%'\nAND a.created_at > DATE_SUB(NOW(), INTERVAL 30 DAY)\nGROUP BY u.id, u.email, u.name, u.softphone_number\nORDER BY sms_count DESC;\n\nselect * from teams where id = 1;\n\nselect * from roles;\n\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1117 and sa.provider = 'hubspot';\nSELECT * FROM activities WHERE uuid_to_bin('8024fffb-2df7-4017-91f4-d9f896050248') = uuid; # 79933459 YES\nSELECT * FROM activities WHERE uuid_to_bin('25529043-8094-4781-927f-4f4da2a8185c') = uuid; # 80186192 NO\nSELECT * FROM crm_configurations WHERE id = 1053;\nSELECT * FROM teams WHERE id = 1117;\nselect * from users where id = 30249;\nselect * from playbooks where id = 5473;\nselect * from playbook_categories where id = 43783;\nselect * from playbook_categories where playbook_id = 5473;\nselect * from crm_fields where id = 659242;\nselect * from crm_field_values where crm_field_id = 659242;\n\nSELECT * FROM crm_field_data fd\n# JOIN crm_fields f ON fd.crm_field_id = f.id\n# JOIN activities a ON fd.activity_id = a.id\nWHERE activity_id = 79933459\n# AND f.crm_provider_id = 'hs_activity_type';\n\n\nSELECT * FROM activity_messages;\nselect * from text_relays where created_at > '2026-05-01';\nselect * from activities where user_id IN (7160, 18608) and created_at > '2026-05-22' order by id desc;\nselect * from users where team_id = 1 and id IN (18608, 13934, 7160);\nselect * from activities where user_id = 7160 order by id desc limit 10;\n\nselect * from accounts where team_id = 1 and name = 'Column5';\n\nselect * from users where name like '%Subra%'; # 31054, 1117\nselect * from teams where id = 1117;\nselect * from activity_searches where user_id = 31054;\nselect * from activity_search_filters where activity_search_id IN (88882, 88902);","depth":4,"on_screen":true,"value":"SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993\nSELECT * FROM users WHERE id = 25061;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 994;\nSELECT * FROM crm_profiles WHERE user_id = 25061;\n\nselect * from crm_configurations where id = 834;\nSELECT * FROM teams WHERE id = 882;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;\n\nSELECT * FROM contacts where crm_configuration_id = 834;\nSELECT * FROM opportunities WHERE team_id = 933\n# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');\nAND id IN (8482561,18352941,19042734,19232139,19445140,19472541);\nSELECT * FROM opportunity_contacts\nWHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 485; #\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nselect crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id\nwhere crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')\n# and l.converted_at IS NOT NULL\n;\n\n# ********************************************************************\nSELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')\nand opportunity_id IS NULL\norder by id desc;\n\nSELECT * FROM teams WHERE id = 604; # 598\nSELECT * FROM activities WHERE id = 74410828; # chelseaw@allvoices.co\nSELECT * FROM accounts WHERE id = 20068382;\nSELECT * FROM accounts WHERE id = 35186038;\n\nSELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 559 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;\nselect * from sidekick_settings where team_id = 781;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100\n\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 711;\nSELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL\nand is_internal = 0 and status = 'completed'\norder by id desc;\n\nSELECT * FROM crm_layout_entities\nWHERE crm_layout_id IN (2352, 2353);\n;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 556 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;\nSELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;\nselect * from contacts\nwhere crm_configuration_id = 530\nand crm_provider_id = 872252;\n\nselect * from activities where crm_configuration_id = 530\nand user_id = 14343 and type like '%softphone%'\nand created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);\n\n\nSELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t\nJOIN crm_configurations c ON t.id = c.team_id\nWHERE t.status = 'active';\n\nSELECT * FROM teams where id = 1091;\nSELECT * FROM crm_configurations where team_id = 1091;\nSELECT * FROM activity_providers where team_id = 1091;\nSELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT * FROM teams WHERE name LIKE '%Leadventure%';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1091 and sa.provider = 'salesforce';\n\nSELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812\nSELECT * FROM teams where id = 862;\nSELECT * FROM crm_configurations where team_id = 862;\nSELECT * FROM activity_providers where team_id = 862;\nSELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT t.id, crm.id, crm.provider, ap.* FROM teams t\njoin crm_configurations crm on t.id = crm.team_id\njoin activity_providers ap on t.id = ap.team_id\nwhere t.status = 'active' and ap.is_enabled = 1\nand crm.provider = 'hubspot'\nand ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',\n 'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');\n\nSELECT * FROM teams where id = 1068;\nSELECT * FROM crm_configurations where team_id = 1068;\nSELECT * FROM activity_providers where team_id = 1068;\n\nSELECT * FROM activities a\nwhere crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')\nand a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'\n )\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by a.id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1068 and sa.provider = 'hubspot';\n\n# ********************************************************************\n# ********************************************************************\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262\nSELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\nselect * from crm_layouts where crm_configuration_id = 834;\nselect * from crm_layout_entities where crm_layout_id = 2780;\nselect * from crm_fields where id IN (321153,321192,321193,321194);\n\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1057 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8\n\nSELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20\n\nSELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10\n\nSELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #\n\nSELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;\nselect * from users where team_id = 51; # 7783\nSELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130\nselect * from activity_searches where user_id = 7783;\nselect * from activity_search_filters where activity_search_id IN (32291, 32292);\n\nSELECT asf.activity_search_id, asf.id, asf.value\nFROM activity_search_filters asf\nWHERE asf.filter = 'group_id'\nAND asf.value IN (\n SELECT CONCAT(\n HEX(SUBSTR(uuid, 5, 4)), '-',\n HEX(SUBSTR(uuid, 3, 2)), '-',\n HEX(SUBSTR(uuid, 1, 2)), '-',\n HEX(SUBSTR(uuid, 9, 2)), '-',\n HEX(SUBSTR(uuid, 11))\n )\n FROM groups\n WHERE deleted_at IS NOT NULL\n);\n\nSELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th\n# ********************************************************************\nSELECT * FROM crm_configurations where provider = 'hubspot';\nSELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133\nSELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null\n# ********************************************************************\n\nselect * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';\nselect\n cp.*\n# DISTINCT t.id\n# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields\nFROM crm_profiles cp\nJOIN crm_configurations crm on crm.id = cp.crm_configuration_id\nJOIN users u on u.id = cp.user_id\nJOIN teams t ON t.id = crm.team_id\nWHERE crm.provider = 'salesforce' and t.status = 'active'\n and cp.archived_at IS NULL and u.deleted_at IS NULL\n and t.id NOT IN (1093)\n and t.id = 2\n and cp.contact_fields IS NULL;\n# and c.crm_provider_id = '003Uu00000ojD4NIAU';\n\nSELECT * FROM users WHERE id = 26484;\nSELECT * FROM crm_profiles WHERE user_id = 26484;\nSELECT * FROM social_accounts WHERE sociable_id = 26484;\nSELECT * FROM crm_configurations where provider = 'salesforce';\nselect * from users where id IN (10022, 10403);\nselect * from users where team_id IN (526);\nselect * from teams where id IN (526, 532);\nselect * from crm_configurations where id IN (500, 516);\nselect * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);\nselect * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 526 and sa.provider = 'salesforce';\nselect * from team_settings where team_id IN (526, 532);\n\nselect * from users where id IN (22824);\nselect * from crm_profiles where crm_configuration_id IN (1026);\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1093 and sa.provider = 'salesforce';\n\nselect * from teams where id = 1099;\nselect * from users where id = 29643\n\nselect * from activity_processing_states;\n\nSELECT * FROM teams where name LIKE '%Fare%'; # 233\nSELECT * FROM opportunities where crm_configuration_id = 215\n# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'\n;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1088 and sa.provider = 'hubspot';\n\nSELECT * FROM teams order by updated_at DESC\nSELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account\n\nselect * from crm_configurations where provider = 'pipedrive';\n\nselect * from teams where id = 957;\nselect * from crm_configurations where id = 957;\n\nSELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743\nSELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;\n\nselect * from users where team_id = 1; # 26726 - Gabriela Dureva\nSELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific\nselect * from activities where user_id = 26726 order by id desc;\nselect * from contacts where crm_configuration_id = 1\nand email IN ('charlotte.ward@prolific.com', 'frankie.bryant@prolific.com'); # 2094416, 2093620\nSELECT * FROM contacts WHERE id = 6284931;\n\nSELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id\nWHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;\n\nselect * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);\nselect * from crm_configurations where id = 1;\n\n43801692-1aeb-32ce-acba-5b80a479701a\n44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b\n405975c0-b3d0-7aaa-821f-09d59cae6dd1\n4caf848d-4bed-2299-b248-7788d41f9fca\n49bedc3f-f196-eef3-89c3-dea6a3b4aa63\n43420989-a09d-b8f8-9806-c8bbf7a02aac\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nSELECT * FROM activities WHERE id = 75461988;\n\nSELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;\n\nselect * from contacts where id = 17900517;\n\nselect * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id\nwhere crm.provider != 'salesforce';\n\nselect * from users where id = 21047;\nSELECT * FROM crm_configurations WHERE id = 892;\nSELECT * FROM teams WHERE id = 942;\nselect * from opportunities where team_id = 942 order by updated_at desc;\nselect * from contacts where team_id = 942 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 942 and sa.provider = 'hubspot';\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430\nSELECT * FROM crm_configurations WHERE id = 1;\nSELECT * FROM teams WHERE crm_id = 1;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nselect id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1\nSELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430\n\nselect * from teams where id = 852;\nselect * from groups where id = 2286;\nselect * from sidekick_settings where team_id = 852;\nselect * from default_activity_types where team_id = 852;\n\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1 AND u.deleted_at IS NULL\nAND u.crm_required = 1\nAND u.team_id = 1\nORDER BY u.team_id;\n\nSELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (\n18481\n );\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1\n AND u.deleted_at IS NULL\n AND u.crm_required = 1\n# AND u.team_id = 1\n AND p.id IS NULL -- Move this condition to WHERE clause\nORDER BY u.team_id;\n\nSELECT * FROM opportunities WHERE id = 20002609;\nselect * from teams where id = 1122; # Velatir, 29953 - christian@velatir.com\nselect * from crm_configurations where id = 1060;\nselect * from crm_layouts where crm_configuration_id = 1060;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1122 and sa.provider = 'hubspot';\nselect * from opportunities where team_id = 1122 order by updated_at desc;\n\nselect * from crm_field_data where object_type = 'contact';\n\nSELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 248 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS\nSELECT * FROM users where id = 24115;\nSELECT * FROM accounts where id = 4002896;\nSELECT * FROM teams WHERE name LIKE '%adswerve%';\nSELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN (\"0069N000003GIQ9QAO\",\"0061r000019yGP9AAM\",\"0066900001S2KWlAAN\",\"0066900001TDpj2AAD\",\"0066900001b8uEwAAI\",\"0069N000001rQi0QAE\",\"006QF00000KD40mYAD\",\"006QF00000LzpRJYAZ\",\"0069N000002uomtQAA\",\"0069N000002xlMLQAY\",\"0066900001NV6ubAAD\",\"0061r00001HJp45AAD\",\"006QF00000uTlUoYAK\",\"006QF00000v0bZqYAI\");\nSELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203\n\nSELECT u.id, u.email, ac.name, a.* FROM activities a\nJOIN users u ON a.user_id = u.id\nJOIN accounts ac ON a.account_id = ac.id\nWHERE\nuuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or\nuuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or\nuuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;\n\nselect * from users where id = 5825;\nSELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;\n\nselect * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;\n19594, 862\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 862 and sa.provider = 'salesforce';\n\nselect * from automated_reports where id = 36;\nselect ar.frequency, r.*, ar.* from automated_report_results r\njoin automated_reports ar on r.report_id = ar.id\nwhere ar.frequency != 'one_off';\n\nselect s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;\nselect * from nudges n where n.activity_search_id\n\nselect * from teams where created_at > '2026-03-09';\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;\n\nselect * from users where team_id = 1 and name like '%Lukas%'; # 7160\n\nSELECT * FROM teams WHERE id = 575;\nselect * from opportunities where team_id = 575;\nSELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,\nselect * from opportunities where team_id = 1126;\nSELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,\nselect * from opportunities where team_id = 1125;\nselect * from contacts c\nwhere c.team_id = 882;\n\nSELECT * FROM activities WHERE id = 76822967;\nSELECT * FROM crm_profiles WHERE user_id = 15440;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 555;\nSELECT * FROM crm_configurations WHERE id = 555;\nSELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 581 and sa.provider = 'salesforce';\n\nSELECT * FROM automated_report_results order by id desc;\n\nselect * from features;\nselect * from team_features where feature_id = 40;\n\nselect * from teams where id = 556;\n\nselect * from automated_reports;\nwhere id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , [\"pdf\",\"podcast\"]\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\nselect * from automated_report_results order by id desc;\nSELECT * FROM automated_report_results WHERE id = 1919;\n\nselect * from automated_report_results WHERE report_id = 54;\n\nselect * from opportunities where id = 7594349;\n\nSELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - jiminnyintegration@lesmills.com\nselect * from playbooks where team_id = 711; # event 226147\nSELECT * FROM playbook_categories WHERE playbook_id = 5515;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';\nSELECT * FROM crm_fields WHERE id = 226147;\nSELECT * FROM crm_field_values WHERE crm_field_id = 226147;\n\nSELECT * FROM crm_configurations WHERE id = 692;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 711 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;\n\nselect * from leads;\n\nselect * from calendars;\n\nSELECT\n t.id AS team_id,\n t.name,\n LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain\nFROM teams t\nJOIN users u ON u.team_id = t.id\nJOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'\nLEFT JOIN team_domains td\n ON td.team_id = t.id\n AND td.deleted_at IS NULL\n AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))\nGROUP BY t.id, t.name, calendar_domain\nORDER BY t.name, calendar_domain;\n\nselect * from users u join calendars c on c.user_id = u.id\nwhere u.team_id = 882;\n\n\nselect * from activities where id = 74049485; # team 563 crm 537\nselect * from activities where id = 73272382; # team 563 crm 537\nselect * from activities where id = 64400389; # team 563 crm 537\nselect * from activities where id = 58081273; # team 563 crm 537\nselect * from activities where id = 54520297; # team 563 crm 537\nselect * from participants where activity_id = 58081273;\n\nselect * from activities where crm_configuration_id = 537 and provider = 'aircall'\nand account_id = 19003658 order by updated_at desc;\n\nselect * from contacts where crm_configuration_id = 537 and id = 35957759;\nselect * from accounts where crm_configuration_id = 537 and id = 19003658;\n\nselect * from automated_report_results where id = 1976;\nselect * from automated_reports where id = 583;\nselect * from activity_searches where id = 87714;\nselect * from activity_search_filters where activity_search_id = 87714;\n\nSELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid\nor uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot';\nselect * from rate_limits;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2\nand id IN (18, 1872);\nselect * from automated_reports where id = 54;\nSELECT * FROM users WHERE id IN (24623,29443,29613);\n\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\n\nselect * from text_relays where created_at > '2026-05-01';\nand id IN (32415, 32416);\n# and id = 32412;\n\nselect * from users where team_id = 2 and email like '%scott%' and id = 29510;\n\nSELECT * FROM activities WHERE uuid_to_bin('67cebfc2-ed56-44a2-8c68-7a0286ed8618') = uuid; # 79763436\n\nSELECT email_provider_id, COUNT(*) as count, GROUP_CONCAT(id) as ids, GROUP_CONCAT(status) as statuses\nFROM text_relays\nWHERE email_provider_id IN ('19e2027868a64b42', '19e2033ed8ea6b10')\nGROUP BY email_provider_id;\nSELECT id, status, telephony_provider_id, created_at\nFROM activities\nWHERE id IN (80028719, 80028846);\nSELECT id, status, code, email_sent_at, created_at, updated_at\nFROM text_relays\nWHERE id IN (32415, 32416);\nSELECT id, status, code, sender, recipient, created_at\nFROM text_relays\nWHERE sender LIKE '%mario.georgiev%' OR sender LIKE '%stoyan.tomov%'\nORDER BY created_at DESC\nLIMIT 10;\n\nSELECT id, uuid, status, code, sender, recipient, created_at, updated_at\nFROM text_relays\nWHERE uuid = uuid_to_bin('0626141c-27a6-4d8c-aff8-7c8020a2c656');\n\n# ***************\nSELECT DISTINCT u.id, u.email, u.name, u.softphone_number, COUNT(a.id) as sms_count\nFROM users u\nINNER JOIN activities a ON u.id = .user_id\nWHERE a.type LIKE 'sms%'\nAND a.created_at > DATE_SUB(NOW(), INTERVAL 30 DAY)\nGROUP BY u.id, u.email, u.name, u.softphone_number\nORDER BY sms_count DESC;\n\nselect * from teams where id = 1;\n\nselect * from roles;\n\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1117 and sa.provider = 'hubspot';\nSELECT * FROM activities WHERE uuid_to_bin('8024fffb-2df7-4017-91f4-d9f896050248') = uuid; # 79933459 YES\nSELECT * FROM activities WHERE uuid_to_bin('25529043-8094-4781-927f-4f4da2a8185c') = uuid; # 80186192 NO\nSELECT * FROM crm_configurations WHERE id = 1053;\nSELECT * FROM teams WHERE id = 1117;\nselect * from users where id = 30249;\nselect * from playbooks where id = 5473;\nselect * from playbook_categories where id = 43783;\nselect * from playbook_categories where playbook_id = 5473;\nselect * from crm_fields where id = 659242;\nselect * from crm_field_values where crm_field_id = 659242;\n\nSELECT * FROM crm_field_data fd\n# JOIN crm_fields f ON fd.crm_field_id = f.id\n# JOIN activities a ON fd.activity_id = a.id\nWHERE activity_id = 79933459\n# AND f.crm_provider_id = 'hs_activity_type';\n\n\nSELECT * FROM activity_messages;\nselect * from text_relays where created_at > '2026-05-01';\nselect * from activities where user_id IN (7160, 18608) and created_at > '2026-05-22' order by id desc;\nselect * from users where team_id = 1 and id IN (18608, 13934, 7160);\nselect * from activities where user_id = 7160 order by id desc limit 10;\n\nselect * from accounts where team_id = 1 and name = 'Column5';\n\nselect * from users where name like '%Subra%'; # 31054, 1117\nselect * from teams where id = 1117;\nselect * from activity_searches where user_id = 31054;\nselect * from activity_search_filters where activity_search_id IN (88882, 88902);","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
2526630547225287665
|
1137771414947247693
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
#12121 on JY-20963-fix-im Project: faVsco.js, menu
#12121 on JY-20963-fix-import-on-deleted-entity, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
12
9
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Hubspot\Journal;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
use Jiminny\Models\Team;
use Jiminny\Repositories\Crm\CrmConfigurationRepository;
use Jiminny\Repositories\TeamRepository;
use Jiminny\Services\Crm\Hubspot\Webhook\WebhookEventProcessor;
class HubspotJournalPollingService
{
private const string [ENV_SECRET];
private const string [ENV_SECRET];
private const string [ENV_SECRET];
private const int LOCK_TTL_SECONDS = 120; // 2 minutes - renewed every 30 seconds
private const int LOCK_RENEWAL_INTERVAL = 30; // Renew lock every 30 seconds
private const int BASE_SLEEP_SECONDS = 5; // Base sleep when no data
private const int MAX_SLEEP_SECONDS = 120; // Maximum sleep duration
private const int EMPTY_THRESHOLD_FOR_BACKOFF = 3; // Empty results before increasing sleep
private const int MAX_CYCLES_DEFAULT = 3000; // Default maximum cycles before stopping
private const int MEMORY_CRITICAL_THRESHOLD = 90; // 90% of memory limit
private const int MAX_BACKOFF_SECONDS = 300;
private const int MAX_OFFSET_RETRIES = 3;
private const int MAX_RUNTIME_SECONDS = 240; // 4 minutes
private const int MAX_EMPTY_RESULTS_BEFORE_EXIT = 5;
private const int LOG_INTERVAL_CYCLES = 10;
private bool $shouldStop = false;
private int $consecutiveEmptyResults = 0;
private array $offsetRetryCount = [];
private int $cycleCount = 0;
private int $startTime = 0;
private int $lastLockRenewal = 0;
private float $totalApiTime = 0;
private float $totalDownloadTime = 0;
private float $totalTransformTime = 0;
private float $totalProcessTime = 0;
private int $totalJournalFilesDownloaded = 0;
private int $totalEventsProcessed = 0;
private int $emptyJournalFiles = 0;
private int $otherPortalSkipped = 0;
public function __construct(
private HubspotJournalApiClient $apiClient,
private JournalEventTransformer $transformer,
private WebhookEventProcessor $eventProcessor
) {
}
/**
* Start continuous polling of the HubSpot journal
*/
public function startPolling(): void
{
$this->startTime = time();
$this->cycleCount = 0;
$this->logPollingStart();
if (! $this->acquirePollingLock()) {
Log::warning('[HubSpot Journal Polling] Another polling process is already running');
return;
}
try {
while ($this->shouldContinuePolling()) {
$this->cycleCount++;
$this->executePollingCycle();
}
} catch (\Throwable $e) {
Log::error('[HubSpot Journal Polling] Error while polling', [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
]);
} finally {
$this->cleanupPollingSession();
}
}
/**
* Perform a single polling cycle
* Returns true if work was found and processed, false if no work available, null if entry was skipped
*/
public function pollOnce(): ?bool
{
$currentOffset = $this->getCurrentOffset();
$apiStart = microtime(true);
$apiResult = $currentOffset === null
? $this->apiClient->getLatestJournalEntry()
: $this->apiClient->getNextJournalEntry($currentOffset);
$this->totalApiTime += (microtime(true) - $apiStart) * 1000;
if (! $apiResult->success) {
return $this->handleApiResult($apiResult, $currentOffset ?? 'latest');
}
if ($apiResult->data === null) {
Log::info('[HubSpot Journal Polling] No data');
return false;
}
$offset = $apiResult->data['currentOffset'];
$s3Url = $apiResult->data['url'];
$retryCount = $this->offsetRetryCount[$offset] ?? 0;
$downloadStart = microtime(true);
$downloadResult = $this->apiClient->downloadJournalFile($s3Url);
$this->totalDownloadTime += (microtime(true) - $downloadStart) * 1000;
if (! $downloadResult->success) {
return $this->handleDownloadResult($downloadResult, $offset, $retryCount);
}
$this->totalJournalFilesDownloaded++;
$journalData = $downloadResult->data;
$transformStart = microtime(true);
try {
$transformedEvents = $this->transformer->transformJournalEvents($journalData);
} catch (\Exception $e) {
return $this->handleTransformationFailure($offset, $retryCount, $e);
}
$this->totalTransformTime += (microtime(true) - $transformStart) * 1000;
unset($journalData);
$processStart = microtime(true);
$eventsCount = count($transformedEvents);
$this->totalEventsProcessed += $eventsCount;
if ($eventsCount === 0) {
$this->emptyJournalFiles++;
} else {
$this->eventProcessor->processEvents($transformedEvents, '[HubSpot Journal Polling]');
}
$this->totalProcessTime += (microtime(true) - $processStart) * 1000;
$this->updateOffset($offset);
unset($transformedEvents);
$this->logProgressIfNeeded();
return $eventsCount > 0;
}
private function logProgressIfNeeded(): void
{
if ($this->cycleCount === 0 || $this->cycleCount % self::LOG_INTERVAL_CYCLES !== 0) {
return;
}
$cycles = $this->cycleCount;
$avgTotal = ($this->totalApiTime + $this->totalDownloadTime + $this->totalTransformTime + $this->totalProcessTime) / $cycles;
Log::info('[HubSpot Journal Polling] Progress', [
'cycles' => $cycles,
'files' => $this->totalJournalFilesDownloaded,
'events' => $this->totalEventsProcessed,
'empty_files' => $this->emptyJournalFiles,
'avg_ms' => round($avgTotal, 1),
'avg_api_ms' => round($this->totalApiTime / $cycles, 1),
'avg_download_ms' => round($this->totalDownloadTime / $cycles, 1),
'avg_transform_ms' => round($this->totalTransformTime / $cycles, 1),
'avg_process_ms' => round($this->totalProcessTime / $cycles, 1),
]);
}
/**
* Get the current polling offset from Redis
*/
private function getCurrentOffset(bool $cacheOnly = false): ?string
{
$offset = Redis::get(self::OFFSET_CACHE_KEY);
if (! $offset && ! $cacheOnly) {
$offset = $this->getDbOffset();
}
return $offset ? (string) $offset : null;
}
/**
* Get the last stored offset from the database
*/
public function getDbOffset(): ?string
{
$jiminnyTeam = $this->getJiminnyTeam();
if (! $jiminnyTeam instanceof Team) {
Log::error('[HubSpot Journal Polling] Jiminny team not found');
return null;
}
$crmRepository = app(CrmConfigurationRepository::class);
$offset = $crmRepository->getSetting($jiminnyTeam->getCrmConfiguration(), 'hubspot_journal_offset');
Log::info('[HubSpot Journal Polling] Getting offset from database', [
'offset' => $offset,
'jiminny_team_id' => $jiminnyTeam->getId(),
]);
return $offset;
}
/**
* Reset the database offset
*/
public function resetDbOffset(): void
{
$jiminnyTeam = $this->getJiminnyTeam();
if (! $jiminnyTeam instanceof Team) {
Log::error('[HubSpot Journal Polling] Jiminny team not found');
return;
}
$crmRepository = app(CrmConfigurationRepository::class);
$crmRepository->updateSetting($jiminnyTeam->getCrmConfiguration(), 'hubspot_journal_offset', '');
Log::info('[HubSpot Journal Polling] Database offset reset');
}
private function getJiminnyTeam(): ?Team
{
$teamRepository = app(TeamRepository::class);
return $teamRepository->getTeamBySlug('jiminny');
}
private function updateDbOffset(string $offset): void
{
$jiminnyTeam = $this->getJiminnyTeam();
if (! $jiminnyTeam instanceof Team) {
Log::error('[HubSpot Journal Polling] Jiminny team not found');
return;
}
$crmRepository = app(CrmConfigurationRepository::class);
$crmRepository->updateSetting($jiminnyTeam->getCrmConfiguration(), 'hubspot_journal_offset', $offset);
}
/**
* Update the polling offset
*/
private function updateOffset(string $offset): void
{
Redis::setex(self::OFFSET_CACHE_KEY, 259200, $offset); // 3 days TTL
$this->clearOffsetRetryCount($offset);
}
/**
* Reset the polling offset
*/
public function resetOffset(): void
{
Redis::del(self::OFFSET_CACHE_KEY);
Log::info('[HubSpot Journal Polling] Reset polling offset');
}
/**
* Set a specific offset (for manual override or recovery)
*/
public function setOffset(string $offset): void
{
$this->updateOffset($offset);
Log::warning('[HubSpot Journal Polling] Offset manually set', [
'offset' => $offset,
]);
}
/**
* Get current polling status
*/
public function getPollingStatus(): array
{
$lockDataJson = Redis::get(self::POLLING_LOCK_KEY);
$lockData = $lockDataJson ? json_decode($lockDataJson, true) : null;
return [
'is_locked' => $lockData !== null,
'current_offset' => $this->getCurrentOffset(),
'lock_expires_at' => $lockData['expires_at'] ?? null,
'lock_acquired_at' => $lockData['acquired_at'] ?? null,
];
}
/**
* Acquire exclusive polling lock to prevent multiple instances
*/
private function acquirePollingLock(): bool
{
$expiresAt = now()->addSeconds(self::LOCK_TTL_SECONDS)->toISOString();
// Use atomic operation to set both lock and expiration data
$lockData = [
'locked' => true,
'expires_at' => $expiresAt,
'acquired_at' => now()->toISOString(),
];
// Use SETNX (SET if Not eXists) for atomic lock acquisition
$lockAcquired = Redis::set(self::POLLING_LOCK_KEY, json_encode($lockData), 'EX', self::LOCK_TTL_SECONDS, 'NX');
if ($lockAcquired) {
$this->lastLockRenewal = time();
Log::info('[HubSpot Journal Polling] Acquired polling lock', [
'expires_at' => $expiresAt,
]);
}
return (bool) $lockAcquired;
}
/**
* Release the polling lock
*/
private function releasePollingLock(): void
{
Redis::del(self::POLLING_LOCK_KEY);
Log::info('[HubSpot Journal Polling] Released polling lock');
}
/**
* Force release the polling lock (for emergency situations)
*/
public function forceReleaseLock(): void
{
$this->releasePollingLock();
Log::warning('[HubSpot Journal Polling] Force released polling lock');
}
/**
* Signal the polling service to stop gracefully
*/
public function requestStop(): void
{
Redis::setex(self::STOP_FLAG_KEY, 300, '1'); // 5 minutes TTL
$this->shouldStop = true;
Log::info('[HubSpot Journal Polling] Stop requested');
}
/**
* Check if polling should stop
*/
private function shouldStop(): bool
{
// Check local flag first (faster)
if ($this->shouldStop) {
return true;
}
// Check Redis flag (for external stop requests)
if (Redis::exists(self::STOP_FLAG_KEY)) {
$this->shouldStop = true;
return true;
}
return false;
}
/**
* Clear the stop flag and reset state to allow service to start
*/
public function clearStopFlag(): void
{
Redis::del(self::STOP_FLAG_KEY);
$this->shouldStop = false;
$this->resetPollingState();
Log::info('[HubSpot Journal Polling] Stop flag cleared and state reset');
}
/**
* Reset polling state without clearing stop flag
*/
private function resetPollingState(): void
{
$this->consecutiveEmptyResults = 0;
$this->cycleCount = 0;
$this->startTime = 0;
$this->totalApiTime = 0;
$this->totalDownloadTime = 0;
$this->totalTransformTime = 0;
$this->totalProcessTime = 0;
$this->totalJournalFilesDownloaded = 0;
$this->totalEventsProcessed = 0;
$this->emptyJournalFiles = 0;
$this->otherPortalSkipped = 0;
}
public function hasStopFlag(): bool
{
return (bool) Redis::exists(self::STOP_FLAG_KEY);
}
/**
* Calculate adaptive sleep duration based on consecutive empty results
*/
private function calculateAdaptiveSleep(): int
{
if ($this->consecutiveEmptyResults < self::EMPTY_THRESHOLD_FOR_BACKOFF) {
return self::BASE_SLEEP_SECONDS; // 5 second
}
// Progressive backoff: 15s -> 30s -> 60s -> 120s (max)
$delay = 3 * self::BASE_SLEEP_SECONDS;
$sleepDuration = $delay * (2 ** ($this->consecutiveEmptyResults - self::EMPTY_THRESHOLD_FOR_BACKOFF));
return min($sleepDuration, self::MAX_SLEEP_SECONDS);
}
private function logPollingStart(): void
{
Log::info('[HubSpot Journal Polling] Service starting', [
'memory_limit' => ini_get('memory_limit'),
'max_execution_time' => ini_get('max_execution_time'),
'initial_memory_mb' => round(memory_get_usage(true) / 1024 / 1024, 2),
]);
}
/**
* Log polling service end information
*/
private function logPollingEnd(): void
{
$runtime = time() - $this->startTime;
$cycles = max($this->cycleCount, 1);
Log::info('[HubSpot Journal Polling] Service ending', [
'runtime_seconds' => $runtime,
'total_cycles' => $this->cycleCount,
'files_downloaded' => $this->totalJournalFilesDownloaded,
'empty_files' => $this->emptyJournalFiles,
'other_portal_skipped' => $this->otherPortalSkipped,
'total_events' => $this->totalEventsProcessed,
'events_per_file' => $this->totalJournalFilesDownloaded > 0
? round($this->totalEventsProcessed / $this->totalJournalFilesDownloaded, 1)
: 0,
'avg_api_ms' => round($this->totalApiTime / $cycles, 1),
'avg_download_ms' => round($this->totalDownloadTime / $cycles, 1),
'avg_transform_ms' => round($this->totalTransformTime / $cycles, 1),
'avg_process_ms' => round($this->totalProcessTime / $cycles, 1),
'peak_memory_mb' => round(memory_get_peak_usage(true) / 1024 / 1024, 2),
]);
}
/**
* Improved stop condition check with clear reasoning
*/
private function shouldContinuePolling(): bool
{
// Check explicit stop request first (fastest check)
if ($this->shouldStop()) {
Log::info('[HubSpot Journal Polling] Stop requested, ending polling');
return false;
}
if ($this->consecutiveEmptyResults >= self::MAX_EMPTY_RESULTS_BEFORE_EXIT) {
Log::warning('[HubSpot Journal Polling] Maximum empty results reached, stopping', [
'empty_results' => $this->consecutiveEmptyResults,
'max_empty_results' => self::MAX_EMPTY_RESULTS_BEFORE_EXIT,
]);
return false;
}
// Check runtime limit (4 minutes)
$runtime = time() - $this->startTime;
if ($runtime >= self::MAX_RUNTIME_SECONDS) {
Log::warning('[HubSpot Journal Polling] Maximum runtime reached, stopping', [
'runtime_seconds' => $runtime,
'runtime_minutes' => round($runtime / 60, 1),
'max_runtime_seconds' => self::MAX_RUNTIME_SECONDS,
]);
return false;
}
// Check memory limits (prevent OOM)
$currentMemory = memory_get_usage(true);
$memoryLimitBytes = $this->parseMemoryLimit(ini_get('memory_limit'));
if ($memoryLimitBytes > 0 && $currentMemory > ($memoryLimitBytes * self::MEMORY_CRITICAL_THRESHOLD / 100)) {
Log::warning('[HubSpot Journal Polling] Memory limit approaching, stopping', [
'current_memory_mb' => round($currentMemory / 1024 / 1024, 2),
'memory_limit' => ini_get('memory_limit'),
'usage_percent' => round(($currentMemory / $memoryLimitBytes) * 100, 1),
]);
return false;
}
// Check for excessive cycles (prevent runaway processes)
if ($this->cycleCount > self::MAX_CYCLES_DEFAULT) {
Log::warning('[HubSpot Journal Polling] Maximum cycles reached, stopping', [
'cycles' => $this->cycleCount,
'max_cycles' => self::MAX_CYCLES_DEFAULT,
]);
return false;
}
return true;
}
/**
* Handle when work is found - reset counters and continue immediately
*/
private function handleWorkFound(): void
{
$this->consecutiveEmptyResults = 0;
}
/**
* Handle when no work is found - implement adaptive sleep
*/
private function handleNoWorkFound(): void
{
$this->consecutiveEmptyResults++;
$sleepDuration = $this->calculateAdaptiveSleep();
Log::debug('[HubSpot Journal Polling] No work found, sleeping', [
'consecutive_empty' => $this->consecutiveEmptyResults,
'sleep_seconds' => $sleepDuration,
'cycle' => $this->cycleCount,
]);
$this->responsiveSleep($sleepDuration);
}
/**
* Sleep with responsive stop checking
*/
private function responsiveSleep(int $seconds): void
{
for ($i = 0; $i < $seconds && $this->shouldContinuePolling(); $i++) {
sleep(1);
}
}
/**
* Parse memory limit string to bytes
*/
private function parseMemoryLimit(string $memoryLimit): int
{
if ($memoryLimit === '-1') {
return 0; // Unlimited
}
$unit = strtolower(substr($memoryLimit, -1));
$value = (int) substr($memoryLimit, 0, -1);
return match ($unit) {
'g' => $value * 1024 * 1024 * 1024,
'm' => $value * 1024 * 1024,
'k' => $value * 1024,
default => (int) $memoryLimit,
};
}
private function executePollingCycle(): void
{
$this->renewLockIfNeeded();
$result = $this->pollOnce();
if ($result === true) {
$this->handleWorkFound();
} elseif ($result === false) {
$this->handleNoWorkFound();
}
}
private function renewLockIfNeeded(): void
{
$now = time();
if ($now - $this->lastLockRenewal >= self::LOCK_RENEWAL_INTERVAL) {
$this->renewPollingLock();
$this->lastLockRenewal = $now;
}
}
private function renewPollingLock(): void
{
$expiresAt = now()->addSeconds(self::LOCK_TTL_SECONDS)->toISOString();
$lockData = [
'locked' => true,
'expires_at' => $expiresAt,
'acquired_at' => now()->toISOString(),
'renewed_at' => now()->toISOString(),
'cycle' => $this->cycleCount,
];
Redis::setex(self::POLLING_LOCK_KEY, self::LOCK_TTL_SECONDS, json_encode($lockData));
Log::debug('[HubSpot Journal Polling] Lock renewed', [
'expires_at' => $expiresAt,
'cycle' => $this->cycleCount,
]);
}
private function handleApiResult(JournalApiResult $result, string $context): bool
{
if ($result->failureType === JournalApiResult::FAILURE_AUTH) {
Log::warning('[HubSpot Journal Polling] Auth failure, will retry next cycle', [
'context' => $context,
]);
return false;
}
if ($result->failureType === JournalApiResult::FAILURE_RATE_LIMIT) {
$waitSeconds = min($result->retryAfterSeconds ?? 60, self::MAX_BACKOFF_SECONDS);
Log::warning('[HubSpot Journal Polling] Rate limit hit, waiting', [
'wait_seconds' => $waitSeconds,
]);
$this->responsiveSleep($waitSeconds);
return false;
}
if ($result->failureType === JournalApiResult::FAILURE_OFFSET_EXPIRED) {
Log::warning('[HubSpot Journal Polling] Offset expired, resetting to fetch latest data', [
'expired_offset' => $context,
]);
$this->resetOffset();
$this->resetDbOffset();
return false;
}
if ($result->isPermanentFailure()) {
Log::error('[HubSpot Journal Polling] Permanent API failure', [
'context' => $context,
'failure_type' => $result->failureType,
'error' => $result->errorMessage,
]);
$this->shouldStop = true;
return false;
}
Log::warning('[HubSpot Journal Polling] Retryable API failure', [
'context' => $context,
'failure_type' => $result->failureType,
'error' => $result->errorMessage,
]);
if ($result->retryAfterSeconds) {
sleep(min($result->retryAfterSeconds, self::MAX_BACKOFF_SECONDS));
}
return false;
}
/**
* Clean up polling session resources
*/
private function cleanupPollingSession(): void
{
$this->logPollingEnd();
$this->storeOffsetInDB();
$this->releasePollingLock();
$this->apiClient->clearPortalCache();
$this->resetPollingState();
}
private function storeOffsetInDB(): void
{
// Save current offset to database before cleanup
$currentOffset = $this->getCurrentOffset(cacheOnly: true);
if ($currentOffset) {
$this->updateDbOffset($currentOffset);
Log::info('[HubSpot Journal Polling] Saved offset to database on cleanup', [
'offset' => $currentOffset,
]);
}
}
private function handleDownloadResult(JournalApiResult $result, string $offset, int $retryCount): ?bool
{
if ($result->failureType === JournalApiResult::FAILURE_UNKNOWN_PORTAL) {
$this->otherPortalSkipped++;
$this->updateOffset($offset);
return null;
}
if ($result->isPermanentFailure()) {
Log::warning('[HubSpot Journal Polling] Permanent failure, skipping offset', [
'offset' => $offset,
'portal_id' => $result->portalId,
'failure_type' => $result->failureType,
'error' => $result->errorMessage,
]);
$this->updateOffset($offset);
$this->clearOffsetRetryCount($offset);
return false;
}
$retryCount++;
if ($retryCount >= self::MAX_OFFSET_RETRIES) {
Log::error('[HubSpot Journal Polling] Max retries reached, skipping offset', [
'offset' => $offset,
'portal_id' => $result->portalId,
'failure_type' => $result->failureType,
'retry_count' => $retryCount,
]);
$this->updateOffset($offset);
$this->clearOffsetRetryCount($offset);
return false;
}
Log::warning('[HubSpot Journal Polling] Retryable failure, will retry', [
'offset' => $offset,
'failure_type' => $result->failureType,
'retry_count' => $retryCount,
'max_retries' => self::MAX_OFFSET_RETRIES,
]);
$this->offsetRetryCount[$offset] = $retryCount;
if ($result->retryAfterSeconds) {
sleep(min($result->retryAfterSeconds, self::MAX_BACKOFF_SECONDS));
}
return false;
}
/**
* Handle transformation failure with retry logic
*/
private function handleTransformationFailure(string $offset, int $retryCount, \Exception $exception): bool
{
$retryCount++;
if ($retryCount >= self::MAX_OFFSET_RETRIES) {
Log::critical('[HubSpot Journal Polling] Max transformation retries reached - SKIPPING offset', [
'offset' => $offset,
'retry_count' => $retryCount,
'error' => $exception->getMessage(),
'trace' => $exception->getTraceAsString(),
]);
// Skip this offset to prevent infinite loop with corrupted data
$this->updateOffset($offset);
$this->clearOffsetRetryCount($offset);
return false;
}
Log::error('[HubSpot Journal Polling] Transformation failed - will retry', [
'offset' => $offset,
'retry_count' => $retryCount,
'max_retries' => self::MAX_OFFSET_RETRIES,
'error' => $exception->getMessage(),
]);
$this->offsetRetryCount[$offset] = $retryCount;
return false;
}
/**
* Clear retry count for an offset after successful processing
*/
private function clearOffsetRetryCount(string $offset): void
{
unset($this->offsetRetryCount[$offset]);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
45
1
41
66
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993
SELECT * FROM users WHERE id = 25061;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 994;
SELECT * FROM crm_profiles WHERE user_id = 25061;
select * from crm_configurations where id = 834;
SELECT * FROM teams WHERE id = 882;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;
SELECT * FROM contacts where crm_configuration_id = 834;
SELECT * FROM opportunities WHERE team_id = 933
# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');
AND id IN (8482561,18352941,19042734,19232139,19445140,19472541);
SELECT * FROM opportunity_contacts
WHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 485; #
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
select crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id
where crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')
# and l.converted_at IS NOT NULL
;
# [PASSWORD_DOTS]
SELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')
and opportunity_id IS NULL
order by id desc;
SELECT * FROM teams WHERE id = 604; # 598
SELECT * FROM activities WHERE id = 74410828; # [EMAIL]
SELECT * FROM accounts WHERE id = 20068382;
SELECT * FROM accounts WHERE id = 35186038;
SELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 559 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;
select * from sidekick_settings where team_id = 781;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100
SELECT * FROM crm_layouts WHERE crm_configuration_id = 711;
SELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL
and is_internal = 0 and status = 'completed'
order by id desc;
SELECT * FROM crm_layout_entities
WHERE crm_layout_id IN (2352, 2353);
;
SELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 556 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;
SELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;
select * from contacts
where crm_configuration_id = 530
and crm_provider_id = 872252;
select * from activities where crm_configuration_id = 530
and user_id = 14343 and type like '%softphone%'
and created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);
SELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t
JOIN crm_configurations c ON t.id = c.team_id
WHERE t.status = 'active';
SELECT * FROM teams where id = 1091;
SELECT * FROM crm_configurations where team_id = 1091;
SELECT * FROM activity_providers where team_id = 1091;
SELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT * FROM teams WHERE name LIKE '%Leadventure%';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1091 and sa.provider = 'salesforce';
SELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812
SELECT * FROM teams where id = 862;
SELECT * FROM crm_configurations where team_id = 862;
SELECT * FROM activity_providers where team_id = 862;
SELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT t.id, crm.id, crm.provider, ap.* FROM teams t
join crm_configurations crm on t.id = crm.team_id
join activity_providers ap on t.id = ap.team_id
where t.status = 'active' and ap.is_enabled = 1
and crm.provider = 'hubspot'
and ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',
'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');
SELECT * FROM teams where id = 1068;
SELECT * FROM crm_configurations where team_id = 1068;
SELECT * FROM activity_providers where team_id = 1068;
SELECT * FROM activities a
where crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')
and a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'
)
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by a.id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1068 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262
SELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
select * from crm_layouts where crm_configuration_id = 834;
select * from crm_layout_entities where crm_layout_id = 2780;
select * from crm_fields where id IN (321153,321192,321193,321194);
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1057 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8
SELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20
SELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10
SELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #
SELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;
select * from users where team_id = 51; # 7783
SELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130
select * from activity_searches where user_id = 7783;
select * from activity_search_filters where activity_search_id IN (32291, 32292);
SELECT asf.activity_search_id, asf.id, asf.value
FROM activity_search_filters asf
WHERE asf.filter = 'group_id'
AND asf.value IN (
SELECT CONCAT(
HEX(SUBSTR(uuid, 5, 4)), '-',
HEX(SUBSTR(uuid, 3, 2)), '-',
HEX(SUBSTR(uuid, 1, 2)), '-',
HEX(SUBSTR(uuid, 9, 2)), '-',
HEX(SUBSTR(uuid, 11))
)
FROM groups
WHERE deleted_at IS NOT NULL
);
SELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where provider = 'hubspot';
SELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133
SELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null
# [PASSWORD_DOTS]
select * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';
select
cp.*
# DISTINCT t.id
# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields
FROM crm_profiles cp
JOIN crm_configurations crm on crm.id = cp.crm_configuration_id
JOIN users u on u.id = cp.user_id
JOIN teams t ON t.id = crm.team_id
WHERE crm.provider = 'salesforce' and t.status = 'active'
and cp.archived_at IS NULL and u.deleted_at IS NULL
and t.id NOT IN (1093)
and t.id = 2
and cp.contact_fields IS NULL;
# and c.crm_provider_id = '003Uu00000ojD4NIAU';
SELECT * FROM users WHERE id = 26484;
SELECT * FROM crm_profiles WHERE user_id = 26484;
SELECT * FROM social_accounts WHERE sociable_id = 26484;
SELECT * FROM crm_configurations where provider = 'salesforce';
select * from users where id IN (10022, 10403);
select * from users where team_id IN (526);
select * from teams where id IN (526, 532);
select * from crm_configurations where id IN (500, 516);
select * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);
select * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 526 and sa.provider = 'salesforce';
select * from team_settings where team_id IN (526, 532);
select * from users where id IN (22824);
select * from crm_profiles where crm_configuration_id IN (1026);
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1093 and sa.provider = 'salesforce';
select * from teams where id = 1099;
select * from users where id = 29643
select * from activity_processing_states;
SELECT * FROM teams where name LIKE '%Fare%'; # 233
SELECT * FROM opportunities where crm_configuration_id = 215
# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'
;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1088 and sa.provider = 'hubspot';
SELECT * FROM teams order by updated_at DESC
SELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account
select * from crm_configurations where provider = 'pipedrive';
select * from teams where id = 957;
select * from crm_configurations where id = 957;
SELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743
SELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;
select * from users where team_id = 1; # 26726 - Gabriela Dureva
SELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific
select * from activities where user_id = 26726 order by id desc;
select * from contacts where crm_configuration_id = 1
and email IN ('[EMAIL]', '[EMAIL]'); # 2094416, 2093620
SELECT * FROM contacts WHERE id = 6284931;
SELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id
WHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;
select * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);
select * from crm_configurations where id = 1;
43801692-1aeb-32ce-acba-5b80a479701a
44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b
405975c0-b3d0-7aaa-821f-09d59cae6dd1
4caf848d-4bed-2299-b248-7788d41f9fca
49bedc3f-f196-eef3-89c3-dea6a3b4aa63
43420989-a09d-b8f8-9806-c8bbf7a02aac
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
SELECT * FROM activities WHERE id = 75461988;
SELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;
select * from contacts where id = 17900517;
select * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id
where crm.provider != 'salesforce';
select * from users where id = 21047;
SELECT * FROM crm_configurations WHERE id = 892;
SELECT * FROM teams WHERE id = 942;
select * from opportunities where team_id = 942 order by updated_at desc;
select * from contacts where team_id = 942 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 942 and sa.provider = 'hubspot';
SELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430
SELECT * FROM crm_configurations WHERE id = 1;
SELECT * FROM teams WHERE crm_id = 1;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
select id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1
SELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430
select * from teams where id = 852;
select * from groups where id = 2286;
select * from sidekick_settings where team_id = 852;
select * from default_activity_types where team_id = 852;
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1 AND u.deleted_at IS NULL
AND u.crm_required = 1
AND u.team_id = 1
ORDER BY u.team_id;
SELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (
18481
);
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1
AND u.deleted_at IS NULL
AND u.crm_required = 1
# AND u.team_id = 1
AND p.id IS NULL -- Move this condition to WHERE clause
ORDER BY u.team_id;
SELECT * FROM opportunities WHERE id = 20002609;
select * from teams where id = 1122; # Velatir, 29953 - [EMAIL]
select * from crm_configurations where id = 1060;
select * from crm_layouts where crm_configuration_id = 1060;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1122 and sa.provider = 'hubspot';
select * from opportunities where team_id = 1122 order by updated_at desc;
select * from crm_field_data where object_type = 'contact';
SELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262
SELECT
CONCAT(u.id, CASE WHEN u.id = t.own...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85262
|
2920
|
10
|
2026-05-28T12:15:57.807255+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970557807_m1.jpg...
|
PhpStorm
|
faVsco.js – HubspotJournalPollingService.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
#12121 on JY-20963-fix-im Project: faVsco.js, menu
#12121 on JY-20963-fix-import-on-deleted-entity, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Hubspot\Journal;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
use Jiminny\Models\Team;
use Jiminny\Repositories\Crm\CrmConfigurationRepository;
use Jiminny\Repositories\TeamRepository;
use Jiminny\Services\Crm\Hubspot\Webhook\WebhookEventProcessor;
class HubspotJournalPollingService
{
private const string [ENV_SECRET];
private const string [ENV_SECRET];
private const string [ENV_SECRET];
private const int LOCK_TTL_SECONDS = 120; // 2 minutes - renewed every 30 seconds
private const int LOCK_RENEWAL_INTERVAL = 30; // Renew lock every 30 seconds
private const int BASE_SLEEP_SECONDS = 5; // Base sleep when no data
private const int MAX_SLEEP_SECONDS = 120; // Maximum sleep duration
private const int EMPTY_THRESHOLD_FOR_BACKOFF = 3; // Empty results before increasing sleep
private const int MAX_CYCLES_DEFAULT = 3000; // Default maximum cycles before stopping
private const int MEMORY_CRITICAL_THRESHOLD = 90; // 90% of memory limit
private const int MAX_BACKOFF_SECONDS = 300;
private const int MAX_OFFSET_RETRIES = 3;
private const int MAX_RUNTIME_SECONDS = 240; // 4 minutes
private const int MAX_EMPTY_RESULTS_BEFORE_EXIT = 5;
private const int LOG_INTERVAL_CYCLES = 10;
private bool $shouldStop = false;
private int $consecutiveEmptyResults = 0;
private array $offsetRetryCount = [];
private int $cycleCount = 0;
private int $startTime = 0;
private int $lastLockRenewal = 0;
private float $totalApiTime = 0;
private float $totalDownloadTime = 0;
private float $totalTransformTime = 0;
private float $totalProcessTime = 0;
private int $totalJournalFilesDownloaded = 0;
private int $totalEventsProcessed = 0;
private int $emptyJournalFiles = 0;
private int $otherPortalSkipped = 0;
public function __construct(
private HubspotJournalApiClient $apiClient,
private JournalEventTransformer $transformer,
private WebhookEventProcessor $eventProcessor
) {
}
/**
* Start continuous polling of the HubSpot journal
*/
public function startPolling(): void
{
$this->startTime = time();
$this->cycleCount = 0;
$this->logPollingStart();
if (! $this->acquirePollingLock()) {
Log::warning('[HubSpot Journal Polling] Another polling process is already running');
return;
}
try {
while ($this->shouldContinuePolling()) {
$this->cycleCount++;
$this->executePollingCycle();
}
} catch (\Throwable $e) {
Log::error('[HubSpot Journal Polling] Error while polling', [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
]);
} finally {
$this->cleanupPollingSession();
}
}
/**
* Perform a single polling cycle
* Returns true if work was found and processed, false if no work available, null if entry was skipped
*/
public function pollOnce(): ?bool
{
$currentOffset = $this->getCurrentOffset();
$apiStart = microtime(true);
$apiResult = $currentOffset === null
? $this->apiClient->getLatestJournalEntry()
: $this->apiClient->getNextJournalEntry($currentOffset);
$this->totalApiTime += (microtime(true) - $apiStart) * 1000;
if (! $apiResult->success) {
return $this->handleApiResult($apiResult, $currentOffset ?? 'latest');
}
if ($apiResult->data === null) {
Log::info('[HubSpot Journal Polling] No data');
return false;
}
$offset = $apiResult->data['currentOffset'];
$s3Url = $apiResult->data['url'];
$retryCount = $this->offsetRetryCount[$offset] ?? 0;
$downloadStart = microtime(true);
$downloadResult = $this->apiClient->downloadJournalFile($s3Url);
$this->totalDownloadTime += (microtime(true) - $downloadStart) * 1000;
if (! $downloadResult->success) {
return $this->handleDownloadResult($downloadResult, $offset, $retryCount);
}
$this->totalJournalFilesDownloaded++;
$journalData = $downloadResult->data;
$transformStart = microtime(true);
try {
$transformedEvents = $this->transformer->transformJournalEvents($journalData);
} catch (\Exception $e) {
return $this->handleTransformationFailure($offset, $retryCount, $e);
}
$this->totalTransformTime += (microtime(true) - $transformStart) * 1000;
unset($journalData);
$processStart = microtime(true);
$eventsCount = count($transformedEvents);
$this->totalEventsProcessed += $eventsCount;
if ($eventsCount === 0) {
$this->emptyJournalFiles++;
} else {
$this->eventProcessor->processEvents($transformedEvents, '[HubSpot Journal Polling]');
}
$this->totalProcessTime += (microtime(true) - $processStart) * 1000;
$this->updateOffset($offset);
unset($transformedEvents);
$this->logProgressIfNeeded();
return $eventsCount > 0;
}
private function logProgressIfNeeded(): void
{
if ($this->cycleCount === 0 || $this->cycleCount % self::LOG_INTERVAL_CYCLES !== 0) {
return;
}
$cycles = $this->cycleCount;
$avgTotal = ($this->totalApiTime + $this->totalDownloadTime + $this->totalTransformTime + $this->totalProcessTime) / $cycles;
Log::info('[HubSpot Journal Polling] Progress', [
'cycles' => $cycles,
'files' => $this->totalJournalFilesDownloaded,
'events' => $this->totalEventsProcessed,
'empty_files' => $this->emptyJournalFiles,
'avg_ms' => round($avgTotal, 1),
'avg_api_ms' => round($this->totalApiTime / $cycles, 1),
'avg_download_ms' => round($this->totalDownloadTime / $cycles, 1),
'avg_transform_ms' => round($this->totalTransformTime / $cycles, 1),
'avg_process_ms' => round($this->totalProcessTime / $cycles, 1),
]);
}
/**
* Get the current polling offset from Redis
*/
private function getCurrentOffset(bool $cacheOnly = false): ?string
{
$offset = Redis::get(self::OFFSET_CACHE_KEY);
if (! $offset && ! $cacheOnly) {
$offset = $this->getDbOffset();
}
return $offset ? (string) $offset : null;
}
/**
* Get the last stored offset from the database
*/
public function getDbOffset(): ?string
{
$jiminnyTeam = $this->getJiminnyTeam();
if (! $jiminnyTeam instanceof Team) {
Log::error('[HubSpot Journal Polling] Jiminny team not found');
return null;
}
$crmRepository = app(CrmConfigurationRepository::class);
$offset = $crmRepository->getSetting($jiminnyTeam->getCrmConfiguration(), 'hubspot_journal_offset');
Log::info('[HubSpot Journal Polling] Getting offset from database', [
'offset' => $offset,
'jiminny_team_id' => $jiminnyTeam->getId(),
]);
return $offset;
}
/**
* Reset the database offset
*/
public function resetDbOffset(): void
{
$jiminnyTeam = $this->getJiminnyTeam();
if (! $jiminnyTeam instanceof Team) {
Log::error('[HubSpot Journal Polling] Jiminny team not found');
return;
}
$crmRepository = app(CrmConfigurationRepository::class);
$crmRepository->updateSetting($jiminnyTeam->getCrmConfiguration(), 'hubspot_journal_offset', '');
Log::info('[HubSpot Journal Polling] Database offset reset');
}
private function getJiminnyTeam(): ?Team
{
$teamRepository = app(TeamRepository::class);
return $teamRepository->getTeamBySlug('jiminny');
}
private function updateDbOffset(string $offset): void
{
$jiminnyTeam = $this->getJiminnyTeam();
if (! $jiminnyTeam instanceof Team) {
Log::error('[HubSpot Journal Polling] Jiminny team not found');
return;
}
$crmRepository = app(CrmConfigurationRepository::class);
$crmRepository->updateSetting($jiminnyTeam->getCrmConfiguration(), 'hubspot_journal_offset', $offset);
}
/**
* Update the polling offset
*/
private function updateOffset(string $offset): void
{
Redis::setex(self::OFFSET_CACHE_KEY, 259200, $offset); // 3 days TTL
$this->clearOffsetRetryCount($offset);
}
/**
* Reset the polling offset
*/
public function resetOffset(): void
{
Redis::del(self::OFFSET_CACHE_KEY);
Log::info('[HubSpot Journal Polling] Reset polling offset');
}
/**
* Set a specific offset (for manual override or recovery)
*/
public function setOffset(string $offset): void
{
$this->updateOffset($offset);
Log::warning('[HubSpot Journal Polling] Offset manually set', [
'offset' => $offset,
]);
}
/**
* Get current polling status
*/
public function getPollingStatus(): array
{
$lockDataJson = Redis::get(self::POLLING_LOCK_KEY);
$lockData = $lockDataJson ? json_decode($lockDataJson, true) : null;
return [
'is_locked' => $lockData !== null,
'current_offset' => $this->getCurrentOffset(),
'lock_expires_at' => $lockData['expires_at'] ?? null,
'lock_acquired_at' => $lockData['acquired_at'] ?? null,
];
}
/**
* Acquire exclusive polling lock to prevent multiple instances
*/
private function acquirePollingLock(): bool
{
$expiresAt = now()->addSeconds(self::LOCK_TTL_SECONDS)->toISOString();
// Use atomic operation to set both lock and expiration data
$lockData = [
'locked' => true,
'expires_at' => $expiresAt,
'acquired_at' => now()->toISOString(),
];
// Use SETNX (SET if Not eXists) for atomic lock acquisition
$lockAcquired = Redis::set(self::POLLING_LOCK_KEY, json_encode($lockData), 'EX', self::LOCK_TTL_SECONDS, 'NX');
if ($lockAcquired) {
$this->lastLockRenewal = time();
Log::info('[HubSpot Journal Polling] Acquired polling lock', [
'expires_at' => $expiresAt,
]);
}
return (bool) $lockAcquired;
}
/**
* Release the polling lock
*/
private function releasePollingLock(): void
{
Redis::del(self::POLLING_LOCK_KEY);
Log::info('[HubSpot Journal Polling] Released polling lock');
}
/**
* Force release the polling lock (for emergency situations)
*/
public function forceReleaseLock(): void
{
$this->releasePollingLock();
Log::warning('[HubSpot Journal Polling] Force released polling lock');
}
/**
* Signal the polling service to stop gracefully
*/
public function requestStop(): void
{
Redis::setex(self::STOP_FLAG_KEY, 300, '1'); // 5 minutes TTL
$this->shouldStop = true;
Log::info('[HubSpot Journal Polling] Stop requested');
}
/**
* Check if polling should stop
*/
private function shouldStop(): bool
{
// Check local flag first (faster)
if ($this->shouldStop) {
return true;
}
// Check Redis flag (for external stop requests)
if (Redis::exists(self::STOP_FLAG_KEY)) {
$this->shouldStop = true;
return true;
}
return false;
}
/**
* Clear the stop flag and reset state to allow service to start
*/
public function clearStopFlag(): void
{
Redis::del(self::STOP_FLAG_KEY);
$this->shouldStop = false;
$this->resetPollingState();
Log::info('[HubSpot Journal Polling] Stop flag cleared and state reset');
}
/**
* Reset polling state without clearing stop flag
*/
private function resetPollingState(): void
{
$this->consecutiveEmptyResults = 0;
$this->cycleCount = 0;
$this->startTime = 0;
$this->totalApiTime = 0;
$this->totalDownloadTime = 0;
$this->totalTransformTime = 0;
$this->totalProcessTime = 0;
$this->totalJournalFilesDownloaded = 0;
$this->totalEventsProcessed = 0;
$this->emptyJournalFiles = 0;
$this->otherPortalSkipped = 0;
}
public function hasStopFlag(): bool
{
return (bool) Redis::exists(self::STOP_FLAG_KEY);
}
/**
* Calculate adaptive sleep duration based on consecutive empty results
*/
private function calculateAdaptiveSleep(): int
{
if ($this->consecutiveEmptyResults < self::EMPTY_THRESHOLD_FOR_BACKOFF) {
return self::BASE_SLEEP_SECONDS; // 5 second
}
// Progressive backoff: 15s -> 30s -> 60s -> 120s (max)
$delay = 3 * self::BASE_SLEEP_SECONDS;
$sleepDuration = $delay * (2 ** ($this->consecutiveEmptyResults - self::EMPTY_THRESHOLD_FOR_BACKOFF));
return min($sleepDuration, self::MAX_SLEEP_SECONDS);
}
private function logPollingStart(): void
{
Log::info('[HubSpot Journal Polling] Service starting', [
'memory_limit' => ini_get('memory_limit'),
'max_execution_time' => ini_get('max_execution_time'),
'initial_memory_mb' => round(memory_get_usage(true) / 1024 / 1024, 2),
]);
}
/**
* Log polling service end information
*/
private function logPollingEnd(): void
{
$runtime = time() - $this->startTime;
$cycles = max($this->cycleCount, 1);
Log::info('[HubSpot Journal Polling] Service ending', [
'runtime_seconds' => $runtime,
'total_cycles' => $this->cycleCount,
'files_downloaded' => $this->totalJournalFilesDownloaded,
'empty_files' => $this->emptyJournalFiles,
'other_portal_skipped' => $this->otherPortalSkipped,
'total_events' => $this->totalEventsProcessed,
'events_per_file' => $this->totalJournalFilesDownloaded > 0
? round($this->totalEventsProcessed / $this->totalJournalFilesDownloaded, 1)
: 0,
'avg_api_ms' => round($this->totalApiTime / $cycles, 1),
'avg_download_ms' => round($this->totalDownloadTime / $cycles, 1),
'avg_transform_ms' => round($this->totalTransformTime / $cycles, 1),
'avg_process_ms' => round($this->totalProcessTime / $cycles, 1),
'peak_memory_mb' => round(memory_get_peak_usage(true) / 1024 / 1024, 2),
]);
}
/**
* Improved stop condition check with clear reasoning
*/
private function shouldContinuePolling(): bool
{
// Check explicit stop request first (fastest check)
if ($this->shouldStop()) {
Log::info('[HubSpot Journal Polling] Stop requested, ending polling');
return false;
}
if ($this->consecutiveEmptyResults >= self::MAX_EMPTY_RESULTS_BEFORE_EXIT) {
Log::warning('[HubSpot Journal Polling] Maximum empty results reached, stopping', [
'empty_results' => $this->consecutiveEmptyResults,
'max_empty_results' => self::MAX_EMPTY_RESULTS_BEFORE_EXIT,
]);
return false;
}
// Check runtime limit (4 minutes)
$runtime = time() - $this->startTime;
if ($runtime >= self::MAX_RUNTIME_SECONDS) {
Log::warning('[HubSpot Journal Polling] Maximum runtime reached, stopping', [
'runtime_seconds' => $runtime,
'runtime_minutes' => round($runtime / 60, 1),
'max_runtime_seconds' => self::MAX_RUNTIME_SECONDS,
]);
return false;
}
// Check memory limits (prevent OOM)
$currentMemory = memory_get_usage(true);
$memoryLimitBytes = $this->parseMemoryLimit(ini_get('memory_limit'));
if ($memoryLimitBytes > 0 && $currentMemory > ($memoryLimitBytes * self::MEMORY_CRITICAL_THRESHOLD / 100)) {
Log::warning('[HubSpot Journal Polling] Memory limit approaching, stopping', [
'current_memory_mb' => round($currentMemory / 1024 / 1024, 2),
'memory_limit' => ini_get('memory_limit'),
'usage_percent' => round(($currentMemory / $memoryLimitBytes) * 100, 1),
]);
return false;
}
// Check for excessive cycles (prevent runaway processes)
if ($this->cycleCount > self::MAX_CYCLES_DEFAULT) {
Log::warning('[HubSpot Journal Polling] Maximum cycles reached, stopping', [
'cycles' => $this->cycleCount,
'max_cycles' => self::MAX_CYCLES_DEFAULT,
]);
return false;
}
return true;
}
/**
* Handle when work is found - reset counters and continue immediately
*/
private function handleWorkFound(): void
{
$this->consecutiveEmptyResults = 0;
}
/**
* Handle when no work is found - implement adaptive sleep
*/
private function handleNoWorkFound(): void
{
$this->consecutiveEmptyResults++;
$sleepDuration = $this->calculateAdaptiveSleep();
Log::debug('[HubSpot Journal Polling] No work found, sleeping', [
'consecutive_empty' => $this->consecutiveEmptyResults,
'sleep_seconds' => $sleepDuration,
'cycle' => $this->cycleCount,
]);
$this->responsiveSleep($sleepDuration);
}
/**
* Sleep with responsive stop checking
*/
private function responsiveSleep(int $seconds): void
{
for ($i = 0; $i < $seconds && $this->shouldContinuePolling(); $i++) {
sleep(1);
}
}
/**
* Parse memory limit string to bytes
*/
private function parseMemoryLimit(string $memoryLimit): int
{
if ($memoryLimit === '-1') {
return 0; // Unlimited
}
$unit = strtolower(substr($memoryLimit, -1));
$value = (int) substr($memoryLimit, 0, -1);
return match ($unit) {
'g' => $value * 1024 * 1024 * 1024,
'm' => $value * 1024 * 1024,
'k' => $value * 1024,
default => (int) $memoryLimit,
};
}
private function executePollingCycle(): void
{
$this->renewLockIfNeeded();
$result = $this->pollOnce();
if ($result === true) {
$this->handleWorkFound();
} elseif ($result === false) {
$this->handleNoWorkFound();
}
}
private function renewLockIfNeeded(): void
{
$now = time();
if ($now - $this->lastLockRenewal >= self::LOCK_RENEWAL_INTERVAL) {
$this->renewPollingLock();
$this->lastLockRenewal = $now;
}
}
private function renewPollingLock(): void
{
$expiresAt = now()->addSeconds(self::LOCK_TTL_SECONDS)->toISOString();
$lockData = [
'locked' => true,
'expires_at' => $expiresAt,
'acquired_at' => now()->toISOString(),
'renewed_at' => now()->toISOString(),
'cycle' => $this->cycleCount,
];
Redis::setex(self::POLLING_LOCK_KEY, self::LOCK_TTL_SECONDS, json_encode($lockData));
Log::debug('[HubSpot Journal Polling] Lock renewed', [
'expires_at' => $expiresAt,
'cycle' => $this->cycleCount,
]);
}
private function handleApiResult(JournalApiResult $result, string $context): bool
{
if ($result->failureType === JournalApiResult::FAILURE_AUTH) {
Log::warning('[HubSpot Journal Polling] Auth failure, will retry next cycle', [
'context' => $context,
]);
return false;
}
if ($result->failureType === JournalApiResult::FAILURE_RATE_LIMIT) {
$waitSeconds = min($result->retryAfterSeconds ?? 60, self::MAX_BACKOFF_SECONDS);
Log::warning('[HubSpot Journal Polling] Rate limit hit, waiting', [
'wait_seconds' => $waitSeconds,
]);
$this->responsiveSleep($waitSeconds);
return false;
}
if ($result->failureType === JournalApiResult::FAILURE_OFFSET_EXPIRED) {
Log::warning('[HubSpot Journal Polling] Offset expired, resetting to fetch latest data', [
'expired_offset' => $context,
]);
$this->resetOffset();
$this->resetDbOffset();
return false;
}
if ($result->isPermanentFailure()) {
Log::error('[HubSpot Journal Polling] Permanent API failure', [
'context' => $context,
'failure_type' => $result->failureType,
'error' => $result->errorMessage,
]);
$this->shouldStop = true;
return false;
}
Log::warning('[HubSpot Journal Polling] Retryable API failure', [
'context' => $context,
'failure_type' => $result->failureType,
'error' => $result->errorMessage,
]);
if ($result->retryAfterSeconds) {
sleep(min($result->retryAfterSeconds, self::MAX_BACKOFF_SECONDS));
}
return false;
}
/**
* Clean up polling session resources
*/
private function cleanupPollingSession(): void
{
$this->logPollingEnd();
$this->storeOffsetInDB();
$this->releasePollingLock();
$this->apiClient->clearPortalCache();
$this->resetPollingState();
}
private function storeOffsetInDB(): void
{
// Save current offset to database before cleanup
$currentOffset = $this->getCurrentOffset(cacheOnly: true);
if ($currentOffset) {
$this->updateDbOffset($currentOffset);
Log::info('[HubSpot Journal Polling] Saved offset to database on cleanup', [
'offset' => $currentOffset,
]);
}
}
private function handleDownloadResult(JournalApiResult $result, string $offset, int $retryCount): ?bool
{
if ($result->failureType === JournalApiResult::FAILURE_UNKNOWN_PORTAL) {
$this->otherPortalSkipped++;
$this->updateOffset($offset);
return null;
}
if ($result->isPermanentFailure()) {
Log::warning('[HubSpot Journal Polling] Permanent failure, skipping offset', [
'offset' => $offset,
'portal_id' => $result->portalId,
'failure_type' => $result->failureType,
'error' => $result->errorMessage,
]);
$this->updateOffset($offset);
$this->clearOffsetRetryCount($offset);
return false;
}
$retryCount++;
if ($retryCount >= self::MAX_OFFSET_RETRIES) {
Log::error('[HubSpot Journal Polling] Max retries reached, skipping offset', [
'offset' => $offset,
'portal_id' => $result->portalId,
'failure_type' => $result->failureType,
'retry_count' => $retryCount,
]);
$this->updateOffset($offset);
$this->clearOffsetRetryCount($offset);
return false;
}
Log::warning('[HubSpot Journal Polling] Retryable failure, will retry', [
'offset' => $offset,
'failure_type' => $result->failureType,
'retry_count' => $retryCount,
'max_retries' => self::MAX_OFFSET_RETRIES,
]);
$this->offsetRetryCount[$offset] = $retryCount;
if ($result->retryAfterSeconds) {
sleep(min($result->retryAfterSeconds, self::MAX_BACKOFF_SECONDS));
}
return false;
}
/**
* Handle transformation failure with retry logic
*/
private function handleTransformationFailure(string $offset, int $retryCount, \Exception $exception): bool
{
$retryCount++;
if ($retryCount >= self::MAX_OFFSET_RETRIES) {
Log::critical('[HubSpot Journal Polling] Max transformation retries reached - SKIPPING offset', [
'offset' => $offset,
'retry_count' => $retryCount,
'error' => $exception->getMessage(),
'trace' => $exception->getTraceAsString(),
]);
// Skip this offset to prevent infinite loop with corrupted data
$this->updateOffset($offset);
$this->clearOffsetRetryCount($offset);
return false;
}
Log::error('[HubSpot Journal Polling] Transformation failed - will retry', [
'offset' => $offset,
'retry_count' => $retryCount,
'max_retries' => self::MAX_OFFSET_RETRIES,
'error' => $exception->getMessage(),
]);
$this->offsetRetryCount[$offset] = $retryCount;
return false;
}
/**
* Clear retry count for an offset after successful processing
*/
private function clearOffsetRetryCount(string $offset): void
{
unset($this->offsetRetryCount[$offset]);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
45
1
41
66
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993
SELECT * FROM users WHERE id = 25061;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 994;
SELECT * FROM crm_profiles WHERE user_id = 25061;
select * from crm_configurations where id = 834;
SELECT * FROM teams WHERE id = 882;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;
SELECT * FROM contacts where crm_configuration_id = 834;
SELECT * FROM opportunities WHERE team_id = 933
# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');
AND id IN (8482561,18352941,19042734,19232139,19445140,19472541);
SELECT * FROM opportunity_contacts
WHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 485; #
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
select crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id
where crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')
# and l.converted_at IS NOT NULL
;
# [PASSWORD_DOTS]
SELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')
and opportunity_id IS NULL
order by id desc;
SELECT * FROM teams WHERE id = 604; # 598
SELECT * FROM activities WHERE id = 74410828; # [EMAIL]
SELECT * FROM accounts WHERE id = 20068382;
SELECT * FROM accounts WHERE id = 35186038;
SELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 559 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;
select * from sidekick_settings where team_id = 781;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100
SELECT * FROM crm_layouts WHERE crm_configuration_id = 711;
SELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL
and is_internal = 0 and status = 'completed'
order by id desc;
SELECT * FROM crm_layout_entities
WHERE crm_layout_id IN (2352, 2353);
;
SELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 556 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;
SELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;
select * from contacts
where crm_configuration_id = 530
and crm_provider_id = 872252;
select * from activities where crm_configuration_id = 530
and user_id = 14343 and type like '%softphone%'
and created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);
SELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t
JOIN crm_configurations c ON t.id = c.team_id
WHERE t.status = 'active';
SELECT * FROM teams where id = 1091;
SELECT * FROM crm_configurations where team_id = 1091;
SELECT * FROM activity_providers where team_id = 1091;
SELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT * FROM teams WHERE name LIKE '%Leadventure%';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1091 and sa.provider = 'salesforce';
SELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812
SELECT * FROM teams where id = 862;
SELECT * FROM crm_configurations where team_id = 862;
SELECT * FROM activity_providers where team_id = 862;
SELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT t.id, crm.id, crm.provider, ap.* FROM teams t
join crm_configurations crm on t.id = crm.team_id
join activity_providers ap on t.id = ap.team_id
where t.status = 'active' and ap.is_enabled = 1
and crm.provider = 'hubspot'
and ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',
'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');
SELECT * FROM teams where id = 1068;
SELECT * FROM crm_configurations where team_id = 1068;
SELECT * FROM activity_providers where team_id = 1068;
SELECT * FROM activities a
where crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')
and a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'
)
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by a.id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1068 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262
SELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
select * from crm_layouts where crm_configuration_id = 834;
select * from crm_layout_entities where crm_layout_id = 2780;
select * from crm_fields where id IN (321153,321192,321193,321194);
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1057 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8
SELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20
SELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10
SELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #
SELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;
select * from users where team_id = 51; # 7783
SELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130
select * from activity_searches where user_id = 7783;
select * from activity_search_filters where activity_search_id IN (32291, 32292);
SELECT asf.activity_search_id, asf.id, asf.value
FROM activity_search_filters asf
WHERE asf.filter = 'group_id'
AND asf.value IN (
SELECT CONCAT(
HEX(SUBSTR(uuid, 5, 4)), '-',
HEX(SUBSTR(uuid, 3, 2)), '-',
HEX(SUBSTR(uuid, 1, 2)), '-',
HEX(SUBSTR(uuid, 9, 2)), '-',
HEX(SUBSTR(uuid, 11))
)
FROM groups
WHERE deleted_at IS NOT NULL
);
SELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where provider = 'hubspot';
SELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133
SELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null
# [PASSWORD_DOTS]
select * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';
select
cp.*
# DISTINCT t.id
# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields
FROM crm_profiles cp
JOIN crm_configurations crm on crm.id = cp.crm_configuration_id
JOIN users u on u.id = cp.user_id
JOIN teams t ON t.id = crm.team_id
WHERE crm.provider = 'salesforce' and t.status = 'active'
and cp.archived_at IS NULL and u.deleted_at IS NULL
and t.id NOT IN (1093)
and t.id = 2
and cp.contact_fields IS NULL;
# and c.crm_provider_id = '003Uu00000ojD4NIAU';
SELECT * FROM users WHERE id = 26484;
SELECT * FROM crm_profiles WHERE user_id = 26484;
SELECT * FROM social_accounts WHERE sociable_id = 26484;
SELECT * FROM crm_configurations where provider = 'salesforce';
select * from users where id IN (10022, 10403);
select * from users where team_id IN (526);
select * from teams where id IN (526, 532);
select * from crm_configurations where id IN (500, 516);
select * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);
select * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 526 and sa.provider = 'salesforce';
select * from team_settings where team_id IN (526, 532);
select * from users where id IN (22824);
select * from crm_profiles where crm_configuration_id IN (1026);
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1093 and sa.provider = 'salesforce';
select * from teams where id = 1099;
select * from users where id = 29643
select * from activity_processing_states;
SELECT * FROM teams where name LIKE '%Fare%'; # 233
SELECT * FROM opportunities where crm_configuration_id = 215
# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'
;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1088 and sa.provider = 'hubspot';
SELECT * FROM teams order by updated_at DESC
SELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account
select * from crm_configurations where provider = 'pipedrive';
select * from teams where id = 957;
select * from crm_configurations where id = 957;
SELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743
SELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;
select * from users where team_id = 1; # 26726 - Gabriela Dureva
SELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific
select * from activities where user_id = 26726 order by id desc;
select * from contacts where crm_configuration_id = 1
and email IN ('[EMAIL]', '[EMAIL]'); # 2094416, 2093620
SELECT * FROM contacts WHERE id = 6284931;
SELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id
WHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;
select * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);
select * from crm_configurations where id = 1;
43801692-1aeb-32ce-acba-5b80a479701a
44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b
405975c0-b3d0-7aaa-821f-09d59cae6dd1
4caf848d-4bed-2299-b248-7788d41f9fca
49bedc3f-f196-eef3-89c3-dea6a3b4aa63
43420989-a09d-b8f8-9806-c8bbf7a02aac
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
SELECT * FROM activities WHERE id = 75461988;
SELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;
select * from contacts where id = 17900517;
select * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id
where crm.provider != 'salesforce';
select * from users where id = 21047;
SELECT * FROM crm_configurations WHERE id = 892;
SELECT * FROM teams WHERE id = 942;
select * from opportunities where team_id = 942 order by updated_at desc;
select * from contacts where team_id = 942 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 942 and sa.provider = 'hubspot';
SELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430
SELECT * FROM crm_configurations WHERE id = 1;
SELECT * FROM teams WHERE crm_id = 1;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
select id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1
SELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430
select * from teams where id = 852;
select * from groups where id = 2286;
select * from sidekick_settings where team_id = 852;
select * from default_activity_types where team_id = 852;
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1 AND u.deleted_at IS NULL
AND u.crm_required = 1
AND u.team_id = 1
ORDER BY u.team_id;
SELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (
18481
);
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1
AND u.deleted_at IS NULL
AND u.crm_required = 1
# AND u.team_id = 1
AND p.id IS NULL -- Move this condition to WHERE clause
ORDER BY u.team_id;
SELECT * FROM opportunities WHERE id = 20002609;
select * from teams where id = 1122; # Velatir, 29953 - [EMAIL]
select * from crm_configurations where id = 1060;
select * from crm_layouts where crm_configuration_id = 1060;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1122 and sa.provider = 'hubspot';
select * from opportunities where team_id = 1122 order by updated_at desc;
select * from crm_field_data where object_type = 'contact';
SELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.em...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12121 on JY-20963-fix-import-on-deleted-entity, menu","depth":5,"on_screen":true,"help_text":"Pull request #12121 exists for current branch JY-20963-fix-import-on-deleted-entity","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Hubspot\\Journal;\n\nuse Illuminate\\Support\\Facades\\Log;\nuse Illuminate\\Support\\Facades\\Redis;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Repositories\\Crm\\CrmConfigurationRepository;\nuse Jiminny\\Repositories\\TeamRepository;\nuse Jiminny\\Services\\Crm\\Hubspot\\Webhook\\WebhookEventProcessor;\n\nclass HubspotJournalPollingService\n{\n private const string OFFSET_CACHE_KEY = 'hubspot_journal_offset';\n private const string POLLING_LOCK_KEY = 'hubspot_journal_polling_lock';\n private const string STOP_FLAG_KEY = 'hubspot_journal_stop_flag';\n private const int LOCK_TTL_SECONDS = 120; // 2 minutes - renewed every 30 seconds\n private const int LOCK_RENEWAL_INTERVAL = 30; // Renew lock every 30 seconds\n private const int BASE_SLEEP_SECONDS = 5; // Base sleep when no data\n private const int MAX_SLEEP_SECONDS = 120; // Maximum sleep duration\n private const int EMPTY_THRESHOLD_FOR_BACKOFF = 3; // Empty results before increasing sleep\n private const int MAX_CYCLES_DEFAULT = 3000; // Default maximum cycles before stopping\n private const int MEMORY_CRITICAL_THRESHOLD = 90; // 90% of memory limit\n private const int MAX_BACKOFF_SECONDS = 300;\n private const int MAX_OFFSET_RETRIES = 3;\n private const int MAX_RUNTIME_SECONDS = 240; // 4 minutes\n private const int MAX_EMPTY_RESULTS_BEFORE_EXIT = 5;\n private const int LOG_INTERVAL_CYCLES = 10;\n\n private bool $shouldStop = false;\n private int $consecutiveEmptyResults = 0;\n private array $offsetRetryCount = [];\n\n private int $cycleCount = 0;\n private int $startTime = 0;\n private int $lastLockRenewal = 0;\n\n private float $totalApiTime = 0;\n private float $totalDownloadTime = 0;\n private float $totalTransformTime = 0;\n private float $totalProcessTime = 0;\n\n private int $totalJournalFilesDownloaded = 0;\n private int $totalEventsProcessed = 0;\n private int $emptyJournalFiles = 0;\n private int $otherPortalSkipped = 0;\n\n public function __construct(\n private HubspotJournalApiClient $apiClient,\n private JournalEventTransformer $transformer,\n private WebhookEventProcessor $eventProcessor\n ) {\n }\n\n /**\n * Start continuous polling of the HubSpot journal\n */\n public function startPolling(): void\n {\n $this->startTime = time();\n $this->cycleCount = 0;\n $this->logPollingStart();\n\n if (! $this->acquirePollingLock()) {\n Log::warning('[HubSpot Journal Polling] Another polling process is already running');\n\n return;\n }\n\n try {\n while ($this->shouldContinuePolling()) {\n $this->cycleCount++;\n $this->executePollingCycle();\n }\n } catch (\\Throwable $e) {\n Log::error('[HubSpot Journal Polling] Error while polling', [\n 'error' => $e->getMessage(),\n 'trace' => $e->getTraceAsString(),\n ]);\n } finally {\n $this->cleanupPollingSession();\n }\n }\n\n /**\n * Perform a single polling cycle\n * Returns true if work was found and processed, false if no work available, null if entry was skipped\n */\n public function pollOnce(): ?bool\n {\n $currentOffset = $this->getCurrentOffset();\n\n $apiStart = microtime(true);\n $apiResult = $currentOffset === null\n ? $this->apiClient->getLatestJournalEntry()\n : $this->apiClient->getNextJournalEntry($currentOffset);\n $this->totalApiTime += (microtime(true) - $apiStart) * 1000;\n\n if (! $apiResult->success) {\n return $this->handleApiResult($apiResult, $currentOffset ?? 'latest');\n }\n\n if ($apiResult->data === null) {\n Log::info('[HubSpot Journal Polling] No data');\n\n return false;\n }\n\n $offset = $apiResult->data['currentOffset'];\n $s3Url = $apiResult->data['url'];\n $retryCount = $this->offsetRetryCount[$offset] ?? 0;\n\n $downloadStart = microtime(true);\n $downloadResult = $this->apiClient->downloadJournalFile($s3Url);\n $this->totalDownloadTime += (microtime(true) - $downloadStart) * 1000;\n\n if (! $downloadResult->success) {\n return $this->handleDownloadResult($downloadResult, $offset, $retryCount);\n }\n\n $this->totalJournalFilesDownloaded++;\n $journalData = $downloadResult->data;\n\n $transformStart = microtime(true);\n\n try {\n $transformedEvents = $this->transformer->transformJournalEvents($journalData);\n } catch (\\Exception $e) {\n return $this->handleTransformationFailure($offset, $retryCount, $e);\n }\n $this->totalTransformTime += (microtime(true) - $transformStart) * 1000;\n unset($journalData);\n\n $processStart = microtime(true);\n $eventsCount = count($transformedEvents);\n $this->totalEventsProcessed += $eventsCount;\n\n if ($eventsCount === 0) {\n $this->emptyJournalFiles++;\n } else {\n $this->eventProcessor->processEvents($transformedEvents, '[HubSpot Journal Polling]');\n }\n $this->totalProcessTime += (microtime(true) - $processStart) * 1000;\n\n $this->updateOffset($offset);\n unset($transformedEvents);\n\n $this->logProgressIfNeeded();\n\n return $eventsCount > 0;\n }\n\n private function logProgressIfNeeded(): void\n {\n if ($this->cycleCount === 0 || $this->cycleCount % self::LOG_INTERVAL_CYCLES !== 0) {\n return;\n }\n\n $cycles = $this->cycleCount;\n $avgTotal = ($this->totalApiTime + $this->totalDownloadTime + $this->totalTransformTime + $this->totalProcessTime) / $cycles;\n\n Log::info('[HubSpot Journal Polling] Progress', [\n 'cycles' => $cycles,\n 'files' => $this->totalJournalFilesDownloaded,\n 'events' => $this->totalEventsProcessed,\n 'empty_files' => $this->emptyJournalFiles,\n 'avg_ms' => round($avgTotal, 1),\n 'avg_api_ms' => round($this->totalApiTime / $cycles, 1),\n 'avg_download_ms' => round($this->totalDownloadTime / $cycles, 1),\n 'avg_transform_ms' => round($this->totalTransformTime / $cycles, 1),\n 'avg_process_ms' => round($this->totalProcessTime / $cycles, 1),\n ]);\n }\n\n /**\n * Get the current polling offset from Redis\n */\n private function getCurrentOffset(bool $cacheOnly = false): ?string\n {\n $offset = Redis::get(self::OFFSET_CACHE_KEY);\n\n if (! $offset && ! $cacheOnly) {\n $offset = $this->getDbOffset();\n }\n\n return $offset ? (string) $offset : null;\n }\n\n /**\n * Get the last stored offset from the database\n */\n public function getDbOffset(): ?string\n {\n $jiminnyTeam = $this->getJiminnyTeam();\n\n if (! $jiminnyTeam instanceof Team) {\n Log::error('[HubSpot Journal Polling] Jiminny team not found');\n\n return null;\n }\n\n $crmRepository = app(CrmConfigurationRepository::class);\n\n $offset = $crmRepository->getSetting($jiminnyTeam->getCrmConfiguration(), 'hubspot_journal_offset');\n\n Log::info('[HubSpot Journal Polling] Getting offset from database', [\n 'offset' => $offset,\n 'jiminny_team_id' => $jiminnyTeam->getId(),\n ]);\n\n return $offset;\n }\n\n /**\n * Reset the database offset\n */\n public function resetDbOffset(): void\n {\n $jiminnyTeam = $this->getJiminnyTeam();\n\n if (! $jiminnyTeam instanceof Team) {\n Log::error('[HubSpot Journal Polling] Jiminny team not found');\n\n return;\n }\n\n $crmRepository = app(CrmConfigurationRepository::class);\n\n $crmRepository->updateSetting($jiminnyTeam->getCrmConfiguration(), 'hubspot_journal_offset', '');\n\n Log::info('[HubSpot Journal Polling] Database offset reset');\n }\n\n private function getJiminnyTeam(): ?Team\n {\n $teamRepository = app(TeamRepository::class);\n\n return $teamRepository->getTeamBySlug('jiminny');\n }\n\n private function updateDbOffset(string $offset): void\n {\n $jiminnyTeam = $this->getJiminnyTeam();\n\n if (! $jiminnyTeam instanceof Team) {\n Log::error('[HubSpot Journal Polling] Jiminny team not found');\n\n return;\n }\n\n $crmRepository = app(CrmConfigurationRepository::class);\n\n $crmRepository->updateSetting($jiminnyTeam->getCrmConfiguration(), 'hubspot_journal_offset', $offset);\n }\n\n /**\n * Update the polling offset\n */\n private function updateOffset(string $offset): void\n {\n Redis::setex(self::OFFSET_CACHE_KEY, 259200, $offset); // 3 days TTL\n $this->clearOffsetRetryCount($offset);\n }\n\n /**\n * Reset the polling offset\n */\n public function resetOffset(): void\n {\n Redis::del(self::OFFSET_CACHE_KEY);\n Log::info('[HubSpot Journal Polling] Reset polling offset');\n }\n\n /**\n * Set a specific offset (for manual override or recovery)\n */\n public function setOffset(string $offset): void\n {\n $this->updateOffset($offset);\n\n Log::warning('[HubSpot Journal Polling] Offset manually set', [\n 'offset' => $offset,\n ]);\n }\n\n /**\n * Get current polling status\n */\n public function getPollingStatus(): array\n {\n $lockDataJson = Redis::get(self::POLLING_LOCK_KEY);\n $lockData = $lockDataJson ? json_decode($lockDataJson, true) : null;\n\n return [\n 'is_locked' => $lockData !== null,\n 'current_offset' => $this->getCurrentOffset(),\n 'lock_expires_at' => $lockData['expires_at'] ?? null,\n 'lock_acquired_at' => $lockData['acquired_at'] ?? null,\n ];\n }\n\n /**\n * Acquire exclusive polling lock to prevent multiple instances\n */\n private function acquirePollingLock(): bool\n {\n $expiresAt = now()->addSeconds(self::LOCK_TTL_SECONDS)->toISOString();\n\n // Use atomic operation to set both lock and expiration data\n $lockData = [\n 'locked' => true,\n 'expires_at' => $expiresAt,\n 'acquired_at' => now()->toISOString(),\n ];\n\n // Use SETNX (SET if Not eXists) for atomic lock acquisition\n $lockAcquired = Redis::set(self::POLLING_LOCK_KEY, json_encode($lockData), 'EX', self::LOCK_TTL_SECONDS, 'NX');\n\n if ($lockAcquired) {\n $this->lastLockRenewal = time();\n Log::info('[HubSpot Journal Polling] Acquired polling lock', [\n 'expires_at' => $expiresAt,\n ]);\n }\n\n return (bool) $lockAcquired;\n }\n\n /**\n * Release the polling lock\n */\n private function releasePollingLock(): void\n {\n Redis::del(self::POLLING_LOCK_KEY);\n Log::info('[HubSpot Journal Polling] Released polling lock');\n }\n\n /**\n * Force release the polling lock (for emergency situations)\n */\n public function forceReleaseLock(): void\n {\n $this->releasePollingLock();\n Log::warning('[HubSpot Journal Polling] Force released polling lock');\n }\n\n /**\n * Signal the polling service to stop gracefully\n */\n public function requestStop(): void\n {\n Redis::setex(self::STOP_FLAG_KEY, 300, '1'); // 5 minutes TTL\n $this->shouldStop = true;\n Log::info('[HubSpot Journal Polling] Stop requested');\n }\n\n /**\n * Check if polling should stop\n */\n private function shouldStop(): bool\n {\n // Check local flag first (faster)\n if ($this->shouldStop) {\n return true;\n }\n\n // Check Redis flag (for external stop requests)\n if (Redis::exists(self::STOP_FLAG_KEY)) {\n $this->shouldStop = true;\n\n return true;\n }\n\n return false;\n }\n\n /**\n * Clear the stop flag and reset state to allow service to start\n */\n public function clearStopFlag(): void\n {\n Redis::del(self::STOP_FLAG_KEY);\n $this->shouldStop = false;\n $this->resetPollingState();\n\n Log::info('[HubSpot Journal Polling] Stop flag cleared and state reset');\n }\n\n /**\n * Reset polling state without clearing stop flag\n */\n private function resetPollingState(): void\n {\n $this->consecutiveEmptyResults = 0;\n $this->cycleCount = 0;\n $this->startTime = 0;\n $this->totalApiTime = 0;\n $this->totalDownloadTime = 0;\n $this->totalTransformTime = 0;\n $this->totalProcessTime = 0;\n $this->totalJournalFilesDownloaded = 0;\n $this->totalEventsProcessed = 0;\n $this->emptyJournalFiles = 0;\n $this->otherPortalSkipped = 0;\n }\n\n public function hasStopFlag(): bool\n {\n return (bool) Redis::exists(self::STOP_FLAG_KEY);\n }\n\n /**\n * Calculate adaptive sleep duration based on consecutive empty results\n */\n private function calculateAdaptiveSleep(): int\n {\n if ($this->consecutiveEmptyResults < self::EMPTY_THRESHOLD_FOR_BACKOFF) {\n return self::BASE_SLEEP_SECONDS; // 5 second\n }\n\n // Progressive backoff: 15s -> 30s -> 60s -> 120s (max)\n $delay = 3 * self::BASE_SLEEP_SECONDS;\n $sleepDuration = $delay * (2 ** ($this->consecutiveEmptyResults - self::EMPTY_THRESHOLD_FOR_BACKOFF));\n\n return min($sleepDuration, self::MAX_SLEEP_SECONDS);\n }\n\n private function logPollingStart(): void\n {\n Log::info('[HubSpot Journal Polling] Service starting', [\n 'memory_limit' => ini_get('memory_limit'),\n 'max_execution_time' => ini_get('max_execution_time'),\n 'initial_memory_mb' => round(memory_get_usage(true) / 1024 / 1024, 2),\n ]);\n }\n\n /**\n * Log polling service end information\n */\n private function logPollingEnd(): void\n {\n $runtime = time() - $this->startTime;\n $cycles = max($this->cycleCount, 1);\n\n Log::info('[HubSpot Journal Polling] Service ending', [\n 'runtime_seconds' => $runtime,\n 'total_cycles' => $this->cycleCount,\n 'files_downloaded' => $this->totalJournalFilesDownloaded,\n 'empty_files' => $this->emptyJournalFiles,\n 'other_portal_skipped' => $this->otherPortalSkipped,\n 'total_events' => $this->totalEventsProcessed,\n 'events_per_file' => $this->totalJournalFilesDownloaded > 0\n ? round($this->totalEventsProcessed / $this->totalJournalFilesDownloaded, 1)\n : 0,\n 'avg_api_ms' => round($this->totalApiTime / $cycles, 1),\n 'avg_download_ms' => round($this->totalDownloadTime / $cycles, 1),\n 'avg_transform_ms' => round($this->totalTransformTime / $cycles, 1),\n 'avg_process_ms' => round($this->totalProcessTime / $cycles, 1),\n 'peak_memory_mb' => round(memory_get_peak_usage(true) / 1024 / 1024, 2),\n ]);\n }\n\n /**\n * Improved stop condition check with clear reasoning\n */\n private function shouldContinuePolling(): bool\n {\n // Check explicit stop request first (fastest check)\n if ($this->shouldStop()) {\n Log::info('[HubSpot Journal Polling] Stop requested, ending polling');\n\n return false;\n }\n\n if ($this->consecutiveEmptyResults >= self::MAX_EMPTY_RESULTS_BEFORE_EXIT) {\n Log::warning('[HubSpot Journal Polling] Maximum empty results reached, stopping', [\n 'empty_results' => $this->consecutiveEmptyResults,\n 'max_empty_results' => self::MAX_EMPTY_RESULTS_BEFORE_EXIT,\n ]);\n\n return false;\n }\n\n // Check runtime limit (4 minutes)\n $runtime = time() - $this->startTime;\n if ($runtime >= self::MAX_RUNTIME_SECONDS) {\n Log::warning('[HubSpot Journal Polling] Maximum runtime reached, stopping', [\n 'runtime_seconds' => $runtime,\n 'runtime_minutes' => round($runtime / 60, 1),\n 'max_runtime_seconds' => self::MAX_RUNTIME_SECONDS,\n ]);\n\n return false;\n }\n\n // Check memory limits (prevent OOM)\n $currentMemory = memory_get_usage(true);\n $memoryLimitBytes = $this->parseMemoryLimit(ini_get('memory_limit'));\n\n if ($memoryLimitBytes > 0 && $currentMemory > ($memoryLimitBytes * self::MEMORY_CRITICAL_THRESHOLD / 100)) {\n Log::warning('[HubSpot Journal Polling] Memory limit approaching, stopping', [\n 'current_memory_mb' => round($currentMemory / 1024 / 1024, 2),\n 'memory_limit' => ini_get('memory_limit'),\n 'usage_percent' => round(($currentMemory / $memoryLimitBytes) * 100, 1),\n ]);\n\n return false;\n }\n\n // Check for excessive cycles (prevent runaway processes)\n if ($this->cycleCount > self::MAX_CYCLES_DEFAULT) {\n Log::warning('[HubSpot Journal Polling] Maximum cycles reached, stopping', [\n 'cycles' => $this->cycleCount,\n 'max_cycles' => self::MAX_CYCLES_DEFAULT,\n ]);\n\n return false;\n }\n\n return true;\n }\n\n /**\n * Handle when work is found - reset counters and continue immediately\n */\n private function handleWorkFound(): void\n {\n $this->consecutiveEmptyResults = 0;\n }\n\n /**\n * Handle when no work is found - implement adaptive sleep\n */\n private function handleNoWorkFound(): void\n {\n $this->consecutiveEmptyResults++;\n $sleepDuration = $this->calculateAdaptiveSleep();\n\n Log::debug('[HubSpot Journal Polling] No work found, sleeping', [\n 'consecutive_empty' => $this->consecutiveEmptyResults,\n 'sleep_seconds' => $sleepDuration,\n 'cycle' => $this->cycleCount,\n ]);\n\n $this->responsiveSleep($sleepDuration);\n }\n\n /**\n * Sleep with responsive stop checking\n */\n private function responsiveSleep(int $seconds): void\n {\n for ($i = 0; $i < $seconds && $this->shouldContinuePolling(); $i++) {\n sleep(1);\n }\n }\n\n /**\n * Parse memory limit string to bytes\n */\n private function parseMemoryLimit(string $memoryLimit): int\n {\n if ($memoryLimit === '-1') {\n return 0; // Unlimited\n }\n\n $unit = strtolower(substr($memoryLimit, -1));\n $value = (int) substr($memoryLimit, 0, -1);\n\n return match ($unit) {\n 'g' => $value * 1024 * 1024 * 1024,\n 'm' => $value * 1024 * 1024,\n 'k' => $value * 1024,\n default => (int) $memoryLimit,\n };\n }\n\n private function executePollingCycle(): void\n {\n $this->renewLockIfNeeded();\n\n $result = $this->pollOnce();\n\n if ($result === true) {\n $this->handleWorkFound();\n } elseif ($result === false) {\n $this->handleNoWorkFound();\n }\n }\n\n private function renewLockIfNeeded(): void\n {\n $now = time();\n if ($now - $this->lastLockRenewal >= self::LOCK_RENEWAL_INTERVAL) {\n $this->renewPollingLock();\n $this->lastLockRenewal = $now;\n }\n }\n\n private function renewPollingLock(): void\n {\n $expiresAt = now()->addSeconds(self::LOCK_TTL_SECONDS)->toISOString();\n\n $lockData = [\n 'locked' => true,\n 'expires_at' => $expiresAt,\n 'acquired_at' => now()->toISOString(),\n 'renewed_at' => now()->toISOString(),\n 'cycle' => $this->cycleCount,\n ];\n\n Redis::setex(self::POLLING_LOCK_KEY, self::LOCK_TTL_SECONDS, json_encode($lockData));\n\n Log::debug('[HubSpot Journal Polling] Lock renewed', [\n 'expires_at' => $expiresAt,\n 'cycle' => $this->cycleCount,\n ]);\n }\n\n private function handleApiResult(JournalApiResult $result, string $context): bool\n {\n if ($result->failureType === JournalApiResult::FAILURE_AUTH) {\n Log::warning('[HubSpot Journal Polling] Auth failure, will retry next cycle', [\n 'context' => $context,\n ]);\n\n return false;\n }\n\n if ($result->failureType === JournalApiResult::FAILURE_RATE_LIMIT) {\n $waitSeconds = min($result->retryAfterSeconds ?? 60, self::MAX_BACKOFF_SECONDS);\n Log::warning('[HubSpot Journal Polling] Rate limit hit, waiting', [\n 'wait_seconds' => $waitSeconds,\n ]);\n $this->responsiveSleep($waitSeconds);\n\n return false;\n }\n\n if ($result->failureType === JournalApiResult::FAILURE_OFFSET_EXPIRED) {\n Log::warning('[HubSpot Journal Polling] Offset expired, resetting to fetch latest data', [\n 'expired_offset' => $context,\n ]);\n $this->resetOffset();\n $this->resetDbOffset();\n\n return false;\n }\n\n if ($result->isPermanentFailure()) {\n Log::error('[HubSpot Journal Polling] Permanent API failure', [\n 'context' => $context,\n 'failure_type' => $result->failureType,\n 'error' => $result->errorMessage,\n ]);\n $this->shouldStop = true;\n\n return false;\n }\n\n Log::warning('[HubSpot Journal Polling] Retryable API failure', [\n 'context' => $context,\n 'failure_type' => $result->failureType,\n 'error' => $result->errorMessage,\n ]);\n\n if ($result->retryAfterSeconds) {\n sleep(min($result->retryAfterSeconds, self::MAX_BACKOFF_SECONDS));\n }\n\n return false;\n }\n\n /**\n * Clean up polling session resources\n */\n private function cleanupPollingSession(): void\n {\n $this->logPollingEnd();\n $this->storeOffsetInDB();\n $this->releasePollingLock();\n $this->apiClient->clearPortalCache();\n $this->resetPollingState();\n }\n\n private function storeOffsetInDB(): void\n {\n // Save current offset to database before cleanup\n $currentOffset = $this->getCurrentOffset(cacheOnly: true);\n if ($currentOffset) {\n $this->updateDbOffset($currentOffset);\n\n Log::info('[HubSpot Journal Polling] Saved offset to database on cleanup', [\n 'offset' => $currentOffset,\n ]);\n }\n }\n\n private function handleDownloadResult(JournalApiResult $result, string $offset, int $retryCount): ?bool\n {\n if ($result->failureType === JournalApiResult::FAILURE_UNKNOWN_PORTAL) {\n $this->otherPortalSkipped++;\n $this->updateOffset($offset);\n\n return null;\n }\n\n if ($result->isPermanentFailure()) {\n Log::warning('[HubSpot Journal Polling] Permanent failure, skipping offset', [\n 'offset' => $offset,\n 'portal_id' => $result->portalId,\n 'failure_type' => $result->failureType,\n 'error' => $result->errorMessage,\n ]);\n $this->updateOffset($offset);\n $this->clearOffsetRetryCount($offset);\n\n return false;\n }\n\n $retryCount++;\n\n if ($retryCount >= self::MAX_OFFSET_RETRIES) {\n Log::error('[HubSpot Journal Polling] Max retries reached, skipping offset', [\n 'offset' => $offset,\n 'portal_id' => $result->portalId,\n 'failure_type' => $result->failureType,\n 'retry_count' => $retryCount,\n ]);\n $this->updateOffset($offset);\n $this->clearOffsetRetryCount($offset);\n\n return false;\n }\n\n Log::warning('[HubSpot Journal Polling] Retryable failure, will retry', [\n 'offset' => $offset,\n 'failure_type' => $result->failureType,\n 'retry_count' => $retryCount,\n 'max_retries' => self::MAX_OFFSET_RETRIES,\n ]);\n\n $this->offsetRetryCount[$offset] = $retryCount;\n\n if ($result->retryAfterSeconds) {\n sleep(min($result->retryAfterSeconds, self::MAX_BACKOFF_SECONDS));\n }\n\n return false;\n }\n\n /**\n * Handle transformation failure with retry logic\n */\n private function handleTransformationFailure(string $offset, int $retryCount, \\Exception $exception): bool\n {\n $retryCount++;\n\n if ($retryCount >= self::MAX_OFFSET_RETRIES) {\n Log::critical('[HubSpot Journal Polling] Max transformation retries reached - SKIPPING offset', [\n 'offset' => $offset,\n 'retry_count' => $retryCount,\n 'error' => $exception->getMessage(),\n 'trace' => $exception->getTraceAsString(),\n ]);\n\n // Skip this offset to prevent infinite loop with corrupted data\n $this->updateOffset($offset);\n $this->clearOffsetRetryCount($offset);\n\n return false;\n }\n\n Log::error('[HubSpot Journal Polling] Transformation failed - will retry', [\n 'offset' => $offset,\n 'retry_count' => $retryCount,\n 'max_retries' => self::MAX_OFFSET_RETRIES,\n 'error' => $exception->getMessage(),\n ]);\n\n $this->offsetRetryCount[$offset] = $retryCount;\n\n return false;\n }\n\n /**\n * Clear retry count for an offset after successful processing\n */\n private function clearOffsetRetryCount(string $offset): void\n {\n unset($this->offsetRetryCount[$offset]);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Hubspot\\Journal;\n\nuse Illuminate\\Support\\Facades\\Log;\nuse Illuminate\\Support\\Facades\\Redis;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Repositories\\Crm\\CrmConfigurationRepository;\nuse Jiminny\\Repositories\\TeamRepository;\nuse Jiminny\\Services\\Crm\\Hubspot\\Webhook\\WebhookEventProcessor;\n\nclass HubspotJournalPollingService\n{\n private const string OFFSET_CACHE_KEY = 'hubspot_journal_offset';\n private const string POLLING_LOCK_KEY = 'hubspot_journal_polling_lock';\n private const string STOP_FLAG_KEY = 'hubspot_journal_stop_flag';\n private const int LOCK_TTL_SECONDS = 120; // 2 minutes - renewed every 30 seconds\n private const int LOCK_RENEWAL_INTERVAL = 30; // Renew lock every 30 seconds\n private const int BASE_SLEEP_SECONDS = 5; // Base sleep when no data\n private const int MAX_SLEEP_SECONDS = 120; // Maximum sleep duration\n private const int EMPTY_THRESHOLD_FOR_BACKOFF = 3; // Empty results before increasing sleep\n private const int MAX_CYCLES_DEFAULT = 3000; // Default maximum cycles before stopping\n private const int MEMORY_CRITICAL_THRESHOLD = 90; // 90% of memory limit\n private const int MAX_BACKOFF_SECONDS = 300;\n private const int MAX_OFFSET_RETRIES = 3;\n private const int MAX_RUNTIME_SECONDS = 240; // 4 minutes\n private const int MAX_EMPTY_RESULTS_BEFORE_EXIT = 5;\n private const int LOG_INTERVAL_CYCLES = 10;\n\n private bool $shouldStop = false;\n private int $consecutiveEmptyResults = 0;\n private array $offsetRetryCount = [];\n\n private int $cycleCount = 0;\n private int $startTime = 0;\n private int $lastLockRenewal = 0;\n\n private float $totalApiTime = 0;\n private float $totalDownloadTime = 0;\n private float $totalTransformTime = 0;\n private float $totalProcessTime = 0;\n\n private int $totalJournalFilesDownloaded = 0;\n private int $totalEventsProcessed = 0;\n private int $emptyJournalFiles = 0;\n private int $otherPortalSkipped = 0;\n\n public function __construct(\n private HubspotJournalApiClient $apiClient,\n private JournalEventTransformer $transformer,\n private WebhookEventProcessor $eventProcessor\n ) {\n }\n\n /**\n * Start continuous polling of the HubSpot journal\n */\n public function startPolling(): void\n {\n $this->startTime = time();\n $this->cycleCount = 0;\n $this->logPollingStart();\n\n if (! $this->acquirePollingLock()) {\n Log::warning('[HubSpot Journal Polling] Another polling process is already running');\n\n return;\n }\n\n try {\n while ($this->shouldContinuePolling()) {\n $this->cycleCount++;\n $this->executePollingCycle();\n }\n } catch (\\Throwable $e) {\n Log::error('[HubSpot Journal Polling] Error while polling', [\n 'error' => $e->getMessage(),\n 'trace' => $e->getTraceAsString(),\n ]);\n } finally {\n $this->cleanupPollingSession();\n }\n }\n\n /**\n * Perform a single polling cycle\n * Returns true if work was found and processed, false if no work available, null if entry was skipped\n */\n public function pollOnce(): ?bool\n {\n $currentOffset = $this->getCurrentOffset();\n\n $apiStart = microtime(true);\n $apiResult = $currentOffset === null\n ? $this->apiClient->getLatestJournalEntry()\n : $this->apiClient->getNextJournalEntry($currentOffset);\n $this->totalApiTime += (microtime(true) - $apiStart) * 1000;\n\n if (! $apiResult->success) {\n return $this->handleApiResult($apiResult, $currentOffset ?? 'latest');\n }\n\n if ($apiResult->data === null) {\n Log::info('[HubSpot Journal Polling] No data');\n\n return false;\n }\n\n $offset = $apiResult->data['currentOffset'];\n $s3Url = $apiResult->data['url'];\n $retryCount = $this->offsetRetryCount[$offset] ?? 0;\n\n $downloadStart = microtime(true);\n $downloadResult = $this->apiClient->downloadJournalFile($s3Url);\n $this->totalDownloadTime += (microtime(true) - $downloadStart) * 1000;\n\n if (! $downloadResult->success) {\n return $this->handleDownloadResult($downloadResult, $offset, $retryCount);\n }\n\n $this->totalJournalFilesDownloaded++;\n $journalData = $downloadResult->data;\n\n $transformStart = microtime(true);\n\n try {\n $transformedEvents = $this->transformer->transformJournalEvents($journalData);\n } catch (\\Exception $e) {\n return $this->handleTransformationFailure($offset, $retryCount, $e);\n }\n $this->totalTransformTime += (microtime(true) - $transformStart) * 1000;\n unset($journalData);\n\n $processStart = microtime(true);\n $eventsCount = count($transformedEvents);\n $this->totalEventsProcessed += $eventsCount;\n\n if ($eventsCount === 0) {\n $this->emptyJournalFiles++;\n } else {\n $this->eventProcessor->processEvents($transformedEvents, '[HubSpot Journal Polling]');\n }\n $this->totalProcessTime += (microtime(true) - $processStart) * 1000;\n\n $this->updateOffset($offset);\n unset($transformedEvents);\n\n $this->logProgressIfNeeded();\n\n return $eventsCount > 0;\n }\n\n private function logProgressIfNeeded(): void\n {\n if ($this->cycleCount === 0 || $this->cycleCount % self::LOG_INTERVAL_CYCLES !== 0) {\n return;\n }\n\n $cycles = $this->cycleCount;\n $avgTotal = ($this->totalApiTime + $this->totalDownloadTime + $this->totalTransformTime + $this->totalProcessTime) / $cycles;\n\n Log::info('[HubSpot Journal Polling] Progress', [\n 'cycles' => $cycles,\n 'files' => $this->totalJournalFilesDownloaded,\n 'events' => $this->totalEventsProcessed,\n 'empty_files' => $this->emptyJournalFiles,\n 'avg_ms' => round($avgTotal, 1),\n 'avg_api_ms' => round($this->totalApiTime / $cycles, 1),\n 'avg_download_ms' => round($this->totalDownloadTime / $cycles, 1),\n 'avg_transform_ms' => round($this->totalTransformTime / $cycles, 1),\n 'avg_process_ms' => round($this->totalProcessTime / $cycles, 1),\n ]);\n }\n\n /**\n * Get the current polling offset from Redis\n */\n private function getCurrentOffset(bool $cacheOnly = false): ?string\n {\n $offset = Redis::get(self::OFFSET_CACHE_KEY);\n\n if (! $offset && ! $cacheOnly) {\n $offset = $this->getDbOffset();\n }\n\n return $offset ? (string) $offset : null;\n }\n\n /**\n * Get the last stored offset from the database\n */\n public function getDbOffset(): ?string\n {\n $jiminnyTeam = $this->getJiminnyTeam();\n\n if (! $jiminnyTeam instanceof Team) {\n Log::error('[HubSpot Journal Polling] Jiminny team not found');\n\n return null;\n }\n\n $crmRepository = app(CrmConfigurationRepository::class);\n\n $offset = $crmRepository->getSetting($jiminnyTeam->getCrmConfiguration(), 'hubspot_journal_offset');\n\n Log::info('[HubSpot Journal Polling] Getting offset from database', [\n 'offset' => $offset,\n 'jiminny_team_id' => $jiminnyTeam->getId(),\n ]);\n\n return $offset;\n }\n\n /**\n * Reset the database offset\n */\n public function resetDbOffset(): void\n {\n $jiminnyTeam = $this->getJiminnyTeam();\n\n if (! $jiminnyTeam instanceof Team) {\n Log::error('[HubSpot Journal Polling] Jiminny team not found');\n\n return;\n }\n\n $crmRepository = app(CrmConfigurationRepository::class);\n\n $crmRepository->updateSetting($jiminnyTeam->getCrmConfiguration(), 'hubspot_journal_offset', '');\n\n Log::info('[HubSpot Journal Polling] Database offset reset');\n }\n\n private function getJiminnyTeam(): ?Team\n {\n $teamRepository = app(TeamRepository::class);\n\n return $teamRepository->getTeamBySlug('jiminny');\n }\n\n private function updateDbOffset(string $offset): void\n {\n $jiminnyTeam = $this->getJiminnyTeam();\n\n if (! $jiminnyTeam instanceof Team) {\n Log::error('[HubSpot Journal Polling] Jiminny team not found');\n\n return;\n }\n\n $crmRepository = app(CrmConfigurationRepository::class);\n\n $crmRepository->updateSetting($jiminnyTeam->getCrmConfiguration(), 'hubspot_journal_offset', $offset);\n }\n\n /**\n * Update the polling offset\n */\n private function updateOffset(string $offset): void\n {\n Redis::setex(self::OFFSET_CACHE_KEY, 259200, $offset); // 3 days TTL\n $this->clearOffsetRetryCount($offset);\n }\n\n /**\n * Reset the polling offset\n */\n public function resetOffset(): void\n {\n Redis::del(self::OFFSET_CACHE_KEY);\n Log::info('[HubSpot Journal Polling] Reset polling offset');\n }\n\n /**\n * Set a specific offset (for manual override or recovery)\n */\n public function setOffset(string $offset): void\n {\n $this->updateOffset($offset);\n\n Log::warning('[HubSpot Journal Polling] Offset manually set', [\n 'offset' => $offset,\n ]);\n }\n\n /**\n * Get current polling status\n */\n public function getPollingStatus(): array\n {\n $lockDataJson = Redis::get(self::POLLING_LOCK_KEY);\n $lockData = $lockDataJson ? json_decode($lockDataJson, true) : null;\n\n return [\n 'is_locked' => $lockData !== null,\n 'current_offset' => $this->getCurrentOffset(),\n 'lock_expires_at' => $lockData['expires_at'] ?? null,\n 'lock_acquired_at' => $lockData['acquired_at'] ?? null,\n ];\n }\n\n /**\n * Acquire exclusive polling lock to prevent multiple instances\n */\n private function acquirePollingLock(): bool\n {\n $expiresAt = now()->addSeconds(self::LOCK_TTL_SECONDS)->toISOString();\n\n // Use atomic operation to set both lock and expiration data\n $lockData = [\n 'locked' => true,\n 'expires_at' => $expiresAt,\n 'acquired_at' => now()->toISOString(),\n ];\n\n // Use SETNX (SET if Not eXists) for atomic lock acquisition\n $lockAcquired = Redis::set(self::POLLING_LOCK_KEY, json_encode($lockData), 'EX', self::LOCK_TTL_SECONDS, 'NX');\n\n if ($lockAcquired) {\n $this->lastLockRenewal = time();\n Log::info('[HubSpot Journal Polling] Acquired polling lock', [\n 'expires_at' => $expiresAt,\n ]);\n }\n\n return (bool) $lockAcquired;\n }\n\n /**\n * Release the polling lock\n */\n private function releasePollingLock(): void\n {\n Redis::del(self::POLLING_LOCK_KEY);\n Log::info('[HubSpot Journal Polling] Released polling lock');\n }\n\n /**\n * Force release the polling lock (for emergency situations)\n */\n public function forceReleaseLock(): void\n {\n $this->releasePollingLock();\n Log::warning('[HubSpot Journal Polling] Force released polling lock');\n }\n\n /**\n * Signal the polling service to stop gracefully\n */\n public function requestStop(): void\n {\n Redis::setex(self::STOP_FLAG_KEY, 300, '1'); // 5 minutes TTL\n $this->shouldStop = true;\n Log::info('[HubSpot Journal Polling] Stop requested');\n }\n\n /**\n * Check if polling should stop\n */\n private function shouldStop(): bool\n {\n // Check local flag first (faster)\n if ($this->shouldStop) {\n return true;\n }\n\n // Check Redis flag (for external stop requests)\n if (Redis::exists(self::STOP_FLAG_KEY)) {\n $this->shouldStop = true;\n\n return true;\n }\n\n return false;\n }\n\n /**\n * Clear the stop flag and reset state to allow service to start\n */\n public function clearStopFlag(): void\n {\n Redis::del(self::STOP_FLAG_KEY);\n $this->shouldStop = false;\n $this->resetPollingState();\n\n Log::info('[HubSpot Journal Polling] Stop flag cleared and state reset');\n }\n\n /**\n * Reset polling state without clearing stop flag\n */\n private function resetPollingState(): void\n {\n $this->consecutiveEmptyResults = 0;\n $this->cycleCount = 0;\n $this->startTime = 0;\n $this->totalApiTime = 0;\n $this->totalDownloadTime = 0;\n $this->totalTransformTime = 0;\n $this->totalProcessTime = 0;\n $this->totalJournalFilesDownloaded = 0;\n $this->totalEventsProcessed = 0;\n $this->emptyJournalFiles = 0;\n $this->otherPortalSkipped = 0;\n }\n\n public function hasStopFlag(): bool\n {\n return (bool) Redis::exists(self::STOP_FLAG_KEY);\n }\n\n /**\n * Calculate adaptive sleep duration based on consecutive empty results\n */\n private function calculateAdaptiveSleep(): int\n {\n if ($this->consecutiveEmptyResults < self::EMPTY_THRESHOLD_FOR_BACKOFF) {\n return self::BASE_SLEEP_SECONDS; // 5 second\n }\n\n // Progressive backoff: 15s -> 30s -> 60s -> 120s (max)\n $delay = 3 * self::BASE_SLEEP_SECONDS;\n $sleepDuration = $delay * (2 ** ($this->consecutiveEmptyResults - self::EMPTY_THRESHOLD_FOR_BACKOFF));\n\n return min($sleepDuration, self::MAX_SLEEP_SECONDS);\n }\n\n private function logPollingStart(): void\n {\n Log::info('[HubSpot Journal Polling] Service starting', [\n 'memory_limit' => ini_get('memory_limit'),\n 'max_execution_time' => ini_get('max_execution_time'),\n 'initial_memory_mb' => round(memory_get_usage(true) / 1024 / 1024, 2),\n ]);\n }\n\n /**\n * Log polling service end information\n */\n private function logPollingEnd(): void\n {\n $runtime = time() - $this->startTime;\n $cycles = max($this->cycleCount, 1);\n\n Log::info('[HubSpot Journal Polling] Service ending', [\n 'runtime_seconds' => $runtime,\n 'total_cycles' => $this->cycleCount,\n 'files_downloaded' => $this->totalJournalFilesDownloaded,\n 'empty_files' => $this->emptyJournalFiles,\n 'other_portal_skipped' => $this->otherPortalSkipped,\n 'total_events' => $this->totalEventsProcessed,\n 'events_per_file' => $this->totalJournalFilesDownloaded > 0\n ? round($this->totalEventsProcessed / $this->totalJournalFilesDownloaded, 1)\n : 0,\n 'avg_api_ms' => round($this->totalApiTime / $cycles, 1),\n 'avg_download_ms' => round($this->totalDownloadTime / $cycles, 1),\n 'avg_transform_ms' => round($this->totalTransformTime / $cycles, 1),\n 'avg_process_ms' => round($this->totalProcessTime / $cycles, 1),\n 'peak_memory_mb' => round(memory_get_peak_usage(true) / 1024 / 1024, 2),\n ]);\n }\n\n /**\n * Improved stop condition check with clear reasoning\n */\n private function shouldContinuePolling(): bool\n {\n // Check explicit stop request first (fastest check)\n if ($this->shouldStop()) {\n Log::info('[HubSpot Journal Polling] Stop requested, ending polling');\n\n return false;\n }\n\n if ($this->consecutiveEmptyResults >= self::MAX_EMPTY_RESULTS_BEFORE_EXIT) {\n Log::warning('[HubSpot Journal Polling] Maximum empty results reached, stopping', [\n 'empty_results' => $this->consecutiveEmptyResults,\n 'max_empty_results' => self::MAX_EMPTY_RESULTS_BEFORE_EXIT,\n ]);\n\n return false;\n }\n\n // Check runtime limit (4 minutes)\n $runtime = time() - $this->startTime;\n if ($runtime >= self::MAX_RUNTIME_SECONDS) {\n Log::warning('[HubSpot Journal Polling] Maximum runtime reached, stopping', [\n 'runtime_seconds' => $runtime,\n 'runtime_minutes' => round($runtime / 60, 1),\n 'max_runtime_seconds' => self::MAX_RUNTIME_SECONDS,\n ]);\n\n return false;\n }\n\n // Check memory limits (prevent OOM)\n $currentMemory = memory_get_usage(true);\n $memoryLimitBytes = $this->parseMemoryLimit(ini_get('memory_limit'));\n\n if ($memoryLimitBytes > 0 && $currentMemory > ($memoryLimitBytes * self::MEMORY_CRITICAL_THRESHOLD / 100)) {\n Log::warning('[HubSpot Journal Polling] Memory limit approaching, stopping', [\n 'current_memory_mb' => round($currentMemory / 1024 / 1024, 2),\n 'memory_limit' => ini_get('memory_limit'),\n 'usage_percent' => round(($currentMemory / $memoryLimitBytes) * 100, 1),\n ]);\n\n return false;\n }\n\n // Check for excessive cycles (prevent runaway processes)\n if ($this->cycleCount > self::MAX_CYCLES_DEFAULT) {\n Log::warning('[HubSpot Journal Polling] Maximum cycles reached, stopping', [\n 'cycles' => $this->cycleCount,\n 'max_cycles' => self::MAX_CYCLES_DEFAULT,\n ]);\n\n return false;\n }\n\n return true;\n }\n\n /**\n * Handle when work is found - reset counters and continue immediately\n */\n private function handleWorkFound(): void\n {\n $this->consecutiveEmptyResults = 0;\n }\n\n /**\n * Handle when no work is found - implement adaptive sleep\n */\n private function handleNoWorkFound(): void\n {\n $this->consecutiveEmptyResults++;\n $sleepDuration = $this->calculateAdaptiveSleep();\n\n Log::debug('[HubSpot Journal Polling] No work found, sleeping', [\n 'consecutive_empty' => $this->consecutiveEmptyResults,\n 'sleep_seconds' => $sleepDuration,\n 'cycle' => $this->cycleCount,\n ]);\n\n $this->responsiveSleep($sleepDuration);\n }\n\n /**\n * Sleep with responsive stop checking\n */\n private function responsiveSleep(int $seconds): void\n {\n for ($i = 0; $i < $seconds && $this->shouldContinuePolling(); $i++) {\n sleep(1);\n }\n }\n\n /**\n * Parse memory limit string to bytes\n */\n private function parseMemoryLimit(string $memoryLimit): int\n {\n if ($memoryLimit === '-1') {\n return 0; // Unlimited\n }\n\n $unit = strtolower(substr($memoryLimit, -1));\n $value = (int) substr($memoryLimit, 0, -1);\n\n return match ($unit) {\n 'g' => $value * 1024 * 1024 * 1024,\n 'm' => $value * 1024 * 1024,\n 'k' => $value * 1024,\n default => (int) $memoryLimit,\n };\n }\n\n private function executePollingCycle(): void\n {\n $this->renewLockIfNeeded();\n\n $result = $this->pollOnce();\n\n if ($result === true) {\n $this->handleWorkFound();\n } elseif ($result === false) {\n $this->handleNoWorkFound();\n }\n }\n\n private function renewLockIfNeeded(): void\n {\n $now = time();\n if ($now - $this->lastLockRenewal >= self::LOCK_RENEWAL_INTERVAL) {\n $this->renewPollingLock();\n $this->lastLockRenewal = $now;\n }\n }\n\n private function renewPollingLock(): void\n {\n $expiresAt = now()->addSeconds(self::LOCK_TTL_SECONDS)->toISOString();\n\n $lockData = [\n 'locked' => true,\n 'expires_at' => $expiresAt,\n 'acquired_at' => now()->toISOString(),\n 'renewed_at' => now()->toISOString(),\n 'cycle' => $this->cycleCount,\n ];\n\n Redis::setex(self::POLLING_LOCK_KEY, self::LOCK_TTL_SECONDS, json_encode($lockData));\n\n Log::debug('[HubSpot Journal Polling] Lock renewed', [\n 'expires_at' => $expiresAt,\n 'cycle' => $this->cycleCount,\n ]);\n }\n\n private function handleApiResult(JournalApiResult $result, string $context): bool\n {\n if ($result->failureType === JournalApiResult::FAILURE_AUTH) {\n Log::warning('[HubSpot Journal Polling] Auth failure, will retry next cycle', [\n 'context' => $context,\n ]);\n\n return false;\n }\n\n if ($result->failureType === JournalApiResult::FAILURE_RATE_LIMIT) {\n $waitSeconds = min($result->retryAfterSeconds ?? 60, self::MAX_BACKOFF_SECONDS);\n Log::warning('[HubSpot Journal Polling] Rate limit hit, waiting', [\n 'wait_seconds' => $waitSeconds,\n ]);\n $this->responsiveSleep($waitSeconds);\n\n return false;\n }\n\n if ($result->failureType === JournalApiResult::FAILURE_OFFSET_EXPIRED) {\n Log::warning('[HubSpot Journal Polling] Offset expired, resetting to fetch latest data', [\n 'expired_offset' => $context,\n ]);\n $this->resetOffset();\n $this->resetDbOffset();\n\n return false;\n }\n\n if ($result->isPermanentFailure()) {\n Log::error('[HubSpot Journal Polling] Permanent API failure', [\n 'context' => $context,\n 'failure_type' => $result->failureType,\n 'error' => $result->errorMessage,\n ]);\n $this->shouldStop = true;\n\n return false;\n }\n\n Log::warning('[HubSpot Journal Polling] Retryable API failure', [\n 'context' => $context,\n 'failure_type' => $result->failureType,\n 'error' => $result->errorMessage,\n ]);\n\n if ($result->retryAfterSeconds) {\n sleep(min($result->retryAfterSeconds, self::MAX_BACKOFF_SECONDS));\n }\n\n return false;\n }\n\n /**\n * Clean up polling session resources\n */\n private function cleanupPollingSession(): void\n {\n $this->logPollingEnd();\n $this->storeOffsetInDB();\n $this->releasePollingLock();\n $this->apiClient->clearPortalCache();\n $this->resetPollingState();\n }\n\n private function storeOffsetInDB(): void\n {\n // Save current offset to database before cleanup\n $currentOffset = $this->getCurrentOffset(cacheOnly: true);\n if ($currentOffset) {\n $this->updateDbOffset($currentOffset);\n\n Log::info('[HubSpot Journal Polling] Saved offset to database on cleanup', [\n 'offset' => $currentOffset,\n ]);\n }\n }\n\n private function handleDownloadResult(JournalApiResult $result, string $offset, int $retryCount): ?bool\n {\n if ($result->failureType === JournalApiResult::FAILURE_UNKNOWN_PORTAL) {\n $this->otherPortalSkipped++;\n $this->updateOffset($offset);\n\n return null;\n }\n\n if ($result->isPermanentFailure()) {\n Log::warning('[HubSpot Journal Polling] Permanent failure, skipping offset', [\n 'offset' => $offset,\n 'portal_id' => $result->portalId,\n 'failure_type' => $result->failureType,\n 'error' => $result->errorMessage,\n ]);\n $this->updateOffset($offset);\n $this->clearOffsetRetryCount($offset);\n\n return false;\n }\n\n $retryCount++;\n\n if ($retryCount >= self::MAX_OFFSET_RETRIES) {\n Log::error('[HubSpot Journal Polling] Max retries reached, skipping offset', [\n 'offset' => $offset,\n 'portal_id' => $result->portalId,\n 'failure_type' => $result->failureType,\n 'retry_count' => $retryCount,\n ]);\n $this->updateOffset($offset);\n $this->clearOffsetRetryCount($offset);\n\n return false;\n }\n\n Log::warning('[HubSpot Journal Polling] Retryable failure, will retry', [\n 'offset' => $offset,\n 'failure_type' => $result->failureType,\n 'retry_count' => $retryCount,\n 'max_retries' => self::MAX_OFFSET_RETRIES,\n ]);\n\n $this->offsetRetryCount[$offset] = $retryCount;\n\n if ($result->retryAfterSeconds) {\n sleep(min($result->retryAfterSeconds, self::MAX_BACKOFF_SECONDS));\n }\n\n return false;\n }\n\n /**\n * Handle transformation failure with retry logic\n */\n private function handleTransformationFailure(string $offset, int $retryCount, \\Exception $exception): bool\n {\n $retryCount++;\n\n if ($retryCount >= self::MAX_OFFSET_RETRIES) {\n Log::critical('[HubSpot Journal Polling] Max transformation retries reached - SKIPPING offset', [\n 'offset' => $offset,\n 'retry_count' => $retryCount,\n 'error' => $exception->getMessage(),\n 'trace' => $exception->getTraceAsString(),\n ]);\n\n // Skip this offset to prevent infinite loop with corrupted data\n $this->updateOffset($offset);\n $this->clearOffsetRetryCount($offset);\n\n return false;\n }\n\n Log::error('[HubSpot Journal Polling] Transformation failed - will retry', [\n 'offset' => $offset,\n 'retry_count' => $retryCount,\n 'max_retries' => self::MAX_OFFSET_RETRIES,\n 'error' => $exception->getMessage(),\n ]);\n\n $this->offsetRetryCount[$offset] = $retryCount;\n\n return false;\n }\n\n /**\n * Clear retry count for an offset after successful processing\n */\n private function clearOffsetRetryCount(string $offset): void\n {\n unset($this->offsetRetryCount[$offset]);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"45","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"41","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"66","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993\nSELECT * FROM users WHERE id = 25061;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 994;\nSELECT * FROM crm_profiles WHERE user_id = 25061;\n\nselect * from crm_configurations where id = 834;\nSELECT * FROM teams WHERE id = 882;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;\n\nSELECT * FROM contacts where crm_configuration_id = 834;\nSELECT * FROM opportunities WHERE team_id = 933\n# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');\nAND id IN (8482561,18352941,19042734,19232139,19445140,19472541);\nSELECT * FROM opportunity_contacts\nWHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 485; #\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nselect crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id\nwhere crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')\n# and l.converted_at IS NOT NULL\n;\n\n# ********************************************************************\nSELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')\nand opportunity_id IS NULL\norder by id desc;\n\nSELECT * FROM teams WHERE id = 604; # 598\nSELECT * FROM activities WHERE id = 74410828; # chelseaw@allvoices.co\nSELECT * FROM accounts WHERE id = 20068382;\nSELECT * FROM accounts WHERE id = 35186038;\n\nSELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 559 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;\nselect * from sidekick_settings where team_id = 781;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100\n\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 711;\nSELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL\nand is_internal = 0 and status = 'completed'\norder by id desc;\n\nSELECT * FROM crm_layout_entities\nWHERE crm_layout_id IN (2352, 2353);\n;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 556 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;\nSELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;\nselect * from contacts\nwhere crm_configuration_id = 530\nand crm_provider_id = 872252;\n\nselect * from activities where crm_configuration_id = 530\nand user_id = 14343 and type like '%softphone%'\nand created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);\n\n\nSELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t\nJOIN crm_configurations c ON t.id = c.team_id\nWHERE t.status = 'active';\n\nSELECT * FROM teams where id = 1091;\nSELECT * FROM crm_configurations where team_id = 1091;\nSELECT * FROM activity_providers where team_id = 1091;\nSELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT * FROM teams WHERE name LIKE '%Leadventure%';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1091 and sa.provider = 'salesforce';\n\nSELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812\nSELECT * FROM teams where id = 862;\nSELECT * FROM crm_configurations where team_id = 862;\nSELECT * FROM activity_providers where team_id = 862;\nSELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT t.id, crm.id, crm.provider, ap.* FROM teams t\njoin crm_configurations crm on t.id = crm.team_id\njoin activity_providers ap on t.id = ap.team_id\nwhere t.status = 'active' and ap.is_enabled = 1\nand crm.provider = 'hubspot'\nand ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',\n 'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');\n\nSELECT * FROM teams where id = 1068;\nSELECT * FROM crm_configurations where team_id = 1068;\nSELECT * FROM activity_providers where team_id = 1068;\n\nSELECT * FROM activities a\nwhere crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')\nand a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'\n )\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by a.id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1068 and sa.provider = 'hubspot';\n\n# ********************************************************************\n# ********************************************************************\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262\nSELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\nselect * from crm_layouts where crm_configuration_id = 834;\nselect * from crm_layout_entities where crm_layout_id = 2780;\nselect * from crm_fields where id IN (321153,321192,321193,321194);\n\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1057 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8\n\nSELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20\n\nSELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10\n\nSELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #\n\nSELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;\nselect * from users where team_id = 51; # 7783\nSELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130\nselect * from activity_searches where user_id = 7783;\nselect * from activity_search_filters where activity_search_id IN (32291, 32292);\n\nSELECT asf.activity_search_id, asf.id, asf.value\nFROM activity_search_filters asf\nWHERE asf.filter = 'group_id'\nAND asf.value IN (\n SELECT CONCAT(\n HEX(SUBSTR(uuid, 5, 4)), '-',\n HEX(SUBSTR(uuid, 3, 2)), '-',\n HEX(SUBSTR(uuid, 1, 2)), '-',\n HEX(SUBSTR(uuid, 9, 2)), '-',\n HEX(SUBSTR(uuid, 11))\n )\n FROM groups\n WHERE deleted_at IS NOT NULL\n);\n\nSELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th\n# ********************************************************************\nSELECT * FROM crm_configurations where provider = 'hubspot';\nSELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133\nSELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null\n# ********************************************************************\n\nselect * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';\nselect\n cp.*\n# DISTINCT t.id\n# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields\nFROM crm_profiles cp\nJOIN crm_configurations crm on crm.id = cp.crm_configuration_id\nJOIN users u on u.id = cp.user_id\nJOIN teams t ON t.id = crm.team_id\nWHERE crm.provider = 'salesforce' and t.status = 'active'\n and cp.archived_at IS NULL and u.deleted_at IS NULL\n and t.id NOT IN (1093)\n and t.id = 2\n and cp.contact_fields IS NULL;\n# and c.crm_provider_id = '003Uu00000ojD4NIAU';\n\nSELECT * FROM users WHERE id = 26484;\nSELECT * FROM crm_profiles WHERE user_id = 26484;\nSELECT * FROM social_accounts WHERE sociable_id = 26484;\nSELECT * FROM crm_configurations where provider = 'salesforce';\nselect * from users where id IN (10022, 10403);\nselect * from users where team_id IN (526);\nselect * from teams where id IN (526, 532);\nselect * from crm_configurations where id IN (500, 516);\nselect * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);\nselect * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 526 and sa.provider = 'salesforce';\nselect * from team_settings where team_id IN (526, 532);\n\nselect * from users where id IN (22824);\nselect * from crm_profiles where crm_configuration_id IN (1026);\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1093 and sa.provider = 'salesforce';\n\nselect * from teams where id = 1099;\nselect * from users where id = 29643\n\nselect * from activity_processing_states;\n\nSELECT * FROM teams where name LIKE '%Fare%'; # 233\nSELECT * FROM opportunities where crm_configuration_id = 215\n# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'\n;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1088 and sa.provider = 'hubspot';\n\nSELECT * FROM teams order by updated_at DESC\nSELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account\n\nselect * from crm_configurations where provider = 'pipedrive';\n\nselect * from teams where id = 957;\nselect * from crm_configurations where id = 957;\n\nSELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743\nSELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;\n\nselect * from users where team_id = 1; # 26726 - Gabriela Dureva\nSELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific\nselect * from activities where user_id = 26726 order by id desc;\nselect * from contacts where crm_configuration_id = 1\nand email IN ('charlotte.ward@prolific.com', 'frankie.bryant@prolific.com'); # 2094416, 2093620\nSELECT * FROM contacts WHERE id = 6284931;\n\nSELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id\nWHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;\n\nselect * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);\nselect * from crm_configurations where id = 1;\n\n43801692-1aeb-32ce-acba-5b80a479701a\n44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b\n405975c0-b3d0-7aaa-821f-09d59cae6dd1\n4caf848d-4bed-2299-b248-7788d41f9fca\n49bedc3f-f196-eef3-89c3-dea6a3b4aa63\n43420989-a09d-b8f8-9806-c8bbf7a02aac\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nSELECT * FROM activities WHERE id = 75461988;\n\nSELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;\n\nselect * from contacts where id = 17900517;\n\nselect * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id\nwhere crm.provider != 'salesforce';\n\nselect * from users where id = 21047;\nSELECT * FROM crm_configurations WHERE id = 892;\nSELECT * FROM teams WHERE id = 942;\nselect * from opportunities where team_id = 942 order by updated_at desc;\nselect * from contacts where team_id = 942 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 942 and sa.provider = 'hubspot';\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430\nSELECT * FROM crm_configurations WHERE id = 1;\nSELECT * FROM teams WHERE crm_id = 1;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nselect id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1\nSELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430\n\nselect * from teams where id = 852;\nselect * from groups where id = 2286;\nselect * from sidekick_settings where team_id = 852;\nselect * from default_activity_types where team_id = 852;\n\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1 AND u.deleted_at IS NULL\nAND u.crm_required = 1\nAND u.team_id = 1\nORDER BY u.team_id;\n\nSELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (\n18481\n );\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1\n AND u.deleted_at IS NULL\n AND u.crm_required = 1\n# AND u.team_id = 1\n AND p.id IS NULL -- Move this condition to WHERE clause\nORDER BY u.team_id;\n\nSELECT * FROM opportunities WHERE id = 20002609;\nselect * from teams where id = 1122; # Velatir, 29953 - christian@velatir.com\nselect * from crm_configurations where id = 1060;\nselect * from crm_layouts where crm_configuration_id = 1060;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1122 and sa.provider = 'hubspot';\nselect * from opportunities where team_id = 1122 order by updated_at desc;\n\nselect * from crm_field_data where object_type = 'contact';\n\nSELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 248 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS\nSELECT * FROM users where id = 24115;\nSELECT * FROM accounts where id = 4002896;\nSELECT * FROM teams WHERE name LIKE '%adswerve%';\nSELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN (\"0069N000003GIQ9QAO\",\"0061r000019yGP9AAM\",\"0066900001S2KWlAAN\",\"0066900001TDpj2AAD\",\"0066900001b8uEwAAI\",\"0069N000001rQi0QAE\",\"006QF00000KD40mYAD\",\"006QF00000LzpRJYAZ\",\"0069N000002uomtQAA\",\"0069N000002xlMLQAY\",\"0066900001NV6ubAAD\",\"0061r00001HJp45AAD\",\"006QF00000uTlUoYAK\",\"006QF00000v0bZqYAI\");\nSELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203\n\nSELECT u.id, u.email, ac.name, a.* FROM activities a\nJOIN users u ON a.user_id = u.id\nJOIN accounts ac ON a.account_id = ac.id\nWHERE\nuuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or\nuuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or\nuuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;\n\nselect * from users where id = 5825;\nSELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;\n\nselect * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;\n19594, 862\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 862 and sa.provider = 'salesforce';\n\nselect * from automated_reports where id = 36;\nselect ar.frequency, r.*, ar.* from automated_report_results r\njoin automated_reports ar on r.report_id = ar.id\nwhere ar.frequency != 'one_off';\n\nselect s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;\nselect * from nudges n where n.activity_search_id\n\nselect * from teams where created_at > '2026-03-09';\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;\n\nselect * from users where team_id = 1 and name like '%Lukas%'; # 7160\n\nSELECT * FROM teams WHERE id = 575;\nselect * from opportunities where team_id = 575;\nSELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,\nselect * from opportunities where team_id = 1126;\nSELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,\nselect * from opportunities where team_id = 1125;\nselect * from contacts c\nwhere c.team_id = 882;\n\nSELECT * FROM activities WHERE id = 76822967;\nSELECT * FROM crm_profiles WHERE user_id = 15440;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 555;\nSELECT * FROM crm_configurations WHERE id = 555;\nSELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 581 and sa.provider = 'salesforce';\n\nSELECT * FROM automated_report_results order by id desc;\n\nselect * from features;\nselect * from team_features where feature_id = 40;\n\nselect * from teams where id = 556;\n\nselect * from automated_reports;\nwhere id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , [\"pdf\",\"podcast\"]\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\nselect * from automated_report_results order by id desc;\nSELECT * FROM automated_report_results WHERE id = 1919;\n\nselect * from automated_report_results WHERE report_id = 54;\n\nselect * from opportunities where id = 7594349;\n\nSELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - jiminnyintegration@lesmills.com\nselect * from playbooks where team_id = 711; # event 226147\nSELECT * FROM playbook_categories WHERE playbook_id = 5515;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';\nSELECT * FROM crm_fields WHERE id = 226147;\nSELECT * FROM crm_field_values WHERE crm_field_id = 226147;\n\nSELECT * FROM crm_configurations WHERE id = 692;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 711 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;\n\nselect * from leads;\n\nselect * from calendars;\n\nSELECT\n t.id AS team_id,\n t.name,\n LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain\nFROM teams t\nJOIN users u ON u.team_id = t.id\nJOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'\nLEFT JOIN team_domains td\n ON td.team_id = t.id\n AND td.deleted_at IS NULL\n AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))\nGROUP BY t.id, t.name, calendar_domain\nORDER BY t.name, calendar_domain;\n\nselect * from users u join calendars c on c.user_id = u.id\nwhere u.team_id = 882;\n\n\nselect * from activities where id = 74049485; # team 563 crm 537\nselect * from activities where id = 73272382; # team 563 crm 537\nselect * from activities where id = 64400389; # team 563 crm 537\nselect * from activities where id = 58081273; # team 563 crm 537\nselect * from activities where id = 54520297; # team 563 crm 537\nselect * from participants where activity_id = 58081273;\n\nselect * from activities where crm_configuration_id = 537 and provider = 'aircall'\nand account_id = 19003658 order by updated_at desc;\n\nselect * from contacts where crm_configuration_id = 537 and id = 35957759;\nselect * from accounts where crm_configuration_id = 537 and id = 19003658;\n\nselect * from automated_report_results where id = 1976;\nselect * from automated_reports where id = 583;\nselect * from activity_searches where id = 87714;\nselect * from activity_search_filters where activity_search_id = 87714;\n\nSELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid\nor uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot';\nselect * from rate_limits;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2\nand id IN (18, 1872);\nselect * from automated_reports where id = 54;\nSELECT * FROM users WHERE id IN (24623,29443,29613);\n\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\n\nselect * from text_relays where created_at > '2026-05-01';\nand id IN (32415, 32416);\n# and id = 32412;\n\nselect * from users where team_id = 2 and email like '%scott%' and id = 29510;\n\nSELECT * FROM activities WHERE uuid_to_bin('67cebfc2-ed56-44a2-8c68-7a0286ed8618') = uuid; # 79763436\n\nSELECT email_provider_id, COUNT(*) as count, GROUP_CONCAT(id) as ids, GROUP_CONCAT(status) as statuses\nFROM text_relays\nWHERE email_provider_id IN ('19e2027868a64b42', '19e2033ed8ea6b10')\nGROUP BY email_provider_id;\nSELECT id, status, telephony_provider_id, created_at\nFROM activities\nWHERE id IN (80028719, 80028846);\nSELECT id, status, code, email_sent_at, created_at, updated_at\nFROM text_relays\nWHERE id IN (32415, 32416);\nSELECT id, status, code, sender, recipient, created_at\nFROM text_relays\nWHERE sender LIKE '%mario.georgiev%' OR sender LIKE '%stoyan.tomov%'\nORDER BY created_at DESC\nLIMIT 10;\n\nSELECT id, uuid, status, code, sender, recipient, created_at, updated_at\nFROM text_relays\nWHERE uuid = uuid_to_bin('0626141c-27a6-4d8c-aff8-7c8020a2c656');\n\n# ***************\nSELECT DISTINCT u.id, u.email, u.name, u.softphone_number, COUNT(a.id) as sms_count\nFROM users u\nINNER JOIN activities a ON u.id = .user_id\nWHERE a.type LIKE 'sms%'\nAND a.created_at > DATE_SUB(NOW(), INTERVAL 30 DAY)\nGROUP BY u.id, u.email, u.name, u.softphone_number\nORDER BY sms_count DESC;\n\nselect * from teams where id = 1;\n\nselect * from roles;\n\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1117 and sa.provider = 'hubspot';\nSELECT * FROM activities WHERE uuid_to_bin('8024fffb-2df7-4017-91f4-d9f896050248') = uuid; # 79933459 YES\nSELECT * FROM activities WHERE uuid_to_bin('25529043-8094-4781-927f-4f4da2a8185c') = uuid; # 80186192 NO\nSELECT * FROM crm_configurations WHERE id = 1053;\nSELECT * FROM teams WHERE id = 1117;\nselect * from users where id = 30249;\nselect * from playbooks where id = 5473;\nselect * from playbook_categories where id = 43783;\nselect * from playbook_categories where playbook_id = 5473;\nselect * from crm_fields where id = 659242;\nselect * from crm_field_values where crm_field_id = 659242;\n\nSELECT * FROM crm_field_data fd\n# JOIN crm_fields f ON fd.crm_field_id = f.id\n# JOIN activities a ON fd.activity_id = a.id\nWHERE activity_id = 79933459\n# AND f.crm_provider_id = 'hs_activity_type';\n\n\nSELECT * FROM activity_messages;\nselect * from text_relays where created_at > '2026-05-01';\nselect * from activities where user_id IN (7160, 18608) and created_at > '2026-05-22' order by id desc;\nselect * from users where team_id = 1 and id IN (18608, 13934, 7160);\nselect * from activities where user_id = 7160 order by id desc limit 10;\n\nselect * from accounts where team_id = 1 and name = 'Column5';\n\nselect * from users where name like '%Subra%'; # 31054, 1117\nselect * from teams where id = 1117;\nselect * from activity_searches where user_id = 31054;\nselect * from activity_search_filters where activity_search_id IN (88882, 88902);","depth":4,"on_screen":true,"value":"SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993\nSELECT * FROM users WHERE id = 25061;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 994;\nSELECT * FROM crm_profiles WHERE user_id = 25061;\n\nselect * from crm_configurations where id = 834;\nSELECT * FROM teams WHERE id = 882;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;\n\nSELECT * FROM contacts where crm_configuration_id = 834;\nSELECT * FROM opportunities WHERE team_id = 933\n# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');\nAND id IN (8482561,18352941,19042734,19232139,19445140,19472541);\nSELECT * FROM opportunity_contacts\nWHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 485; #\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nselect crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id\nwhere crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')\n# and l.converted_at IS NOT NULL\n;\n\n# ********************************************************************\nSELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')\nand opportunity_id IS NULL\norder by id desc;\n\nSELECT * FROM teams WHERE id = 604; # 598\nSELECT * FROM activities WHERE id = 74410828; # chelseaw@allvoices.co\nSELECT * FROM accounts WHERE id = 20068382;\nSELECT * FROM accounts WHERE id = 35186038;\n\nSELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 559 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;\nselect * from sidekick_settings where team_id = 781;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100\n\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 711;\nSELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL\nand is_internal = 0 and status = 'completed'\norder by id desc;\n\nSELECT * FROM crm_layout_entities\nWHERE crm_layout_id IN (2352, 2353);\n;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 556 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;\nSELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;\nselect * from contacts\nwhere crm_configuration_id = 530\nand crm_provider_id = 872252;\n\nselect * from activities where crm_configuration_id = 530\nand user_id = 14343 and type like '%softphone%'\nand created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);\n\n\nSELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t\nJOIN crm_configurations c ON t.id = c.team_id\nWHERE t.status = 'active';\n\nSELECT * FROM teams where id = 1091;\nSELECT * FROM crm_configurations where team_id = 1091;\nSELECT * FROM activity_providers where team_id = 1091;\nSELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT * FROM teams WHERE name LIKE '%Leadventure%';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1091 and sa.provider = 'salesforce';\n\nSELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812\nSELECT * FROM teams where id = 862;\nSELECT * FROM crm_configurations where team_id = 862;\nSELECT * FROM activity_providers where team_id = 862;\nSELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT t.id, crm.id, crm.provider, ap.* FROM teams t\njoin crm_configurations crm on t.id = crm.team_id\njoin activity_providers ap on t.id = ap.team_id\nwhere t.status = 'active' and ap.is_enabled = 1\nand crm.provider = 'hubspot'\nand ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',\n 'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');\n\nSELECT * FROM teams where id = 1068;\nSELECT * FROM crm_configurations where team_id = 1068;\nSELECT * FROM activity_providers where team_id = 1068;\n\nSELECT * FROM activities a\nwhere crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')\nand a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'\n )\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by a.id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1068 and sa.provider = 'hubspot';\n\n# ********************************************************************\n# ********************************************************************\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262\nSELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\nselect * from crm_layouts where crm_configuration_id = 834;\nselect * from crm_layout_entities where crm_layout_id = 2780;\nselect * from crm_fields where id IN (321153,321192,321193,321194);\n\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1057 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8\n\nSELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20\n\nSELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10\n\nSELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #\n\nSELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;\nselect * from users where team_id = 51; # 7783\nSELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130\nselect * from activity_searches where user_id = 7783;\nselect * from activity_search_filters where activity_search_id IN (32291, 32292);\n\nSELECT asf.activity_search_id, asf.id, asf.value\nFROM activity_search_filters asf\nWHERE asf.filter = 'group_id'\nAND asf.value IN (\n SELECT CONCAT(\n HEX(SUBSTR(uuid, 5, 4)), '-',\n HEX(SUBSTR(uuid, 3, 2)), '-',\n HEX(SUBSTR(uuid, 1, 2)), '-',\n HEX(SUBSTR(uuid, 9, 2)), '-',\n HEX(SUBSTR(uuid, 11))\n )\n FROM groups\n WHERE deleted_at IS NOT NULL\n);\n\nSELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th\n# ********************************************************************\nSELECT * FROM crm_configurations where provider = 'hubspot';\nSELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133\nSELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null\n# ********************************************************************\n\nselect * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';\nselect\n cp.*\n# DISTINCT t.id\n# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields\nFROM crm_profiles cp\nJOIN crm_configurations crm on crm.id = cp.crm_configuration_id\nJOIN users u on u.id = cp.user_id\nJOIN teams t ON t.id = crm.team_id\nWHERE crm.provider = 'salesforce' and t.status = 'active'\n and cp.archived_at IS NULL and u.deleted_at IS NULL\n and t.id NOT IN (1093)\n and t.id = 2\n and cp.contact_fields IS NULL;\n# and c.crm_provider_id = '003Uu00000ojD4NIAU';\n\nSELECT * FROM users WHERE id = 26484;\nSELECT * FROM crm_profiles WHERE user_id = 26484;\nSELECT * FROM social_accounts WHERE sociable_id = 26484;\nSELECT * FROM crm_configurations where provider = 'salesforce';\nselect * from users where id IN (10022, 10403);\nselect * from users where team_id IN (526);\nselect * from teams where id IN (526, 532);\nselect * from crm_configurations where id IN (500, 516);\nselect * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);\nselect * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 526 and sa.provider = 'salesforce';\nselect * from team_settings where team_id IN (526, 532);\n\nselect * from users where id IN (22824);\nselect * from crm_profiles where crm_configuration_id IN (1026);\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1093 and sa.provider = 'salesforce';\n\nselect * from teams where id = 1099;\nselect * from users where id = 29643\n\nselect * from activity_processing_states;\n\nSELECT * FROM teams where name LIKE '%Fare%'; # 233\nSELECT * FROM opportunities where crm_configuration_id = 215\n# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'\n;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1088 and sa.provider = 'hubspot';\n\nSELECT * FROM teams order by updated_at DESC\nSELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account\n\nselect * from crm_configurations where provider = 'pipedrive';\n\nselect * from teams where id = 957;\nselect * from crm_configurations where id = 957;\n\nSELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743\nSELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;\n\nselect * from users where team_id = 1; # 26726 - Gabriela Dureva\nSELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific\nselect * from activities where user_id = 26726 order by id desc;\nselect * from contacts where crm_configuration_id = 1\nand email IN ('charlotte.ward@prolific.com', 'frankie.bryant@prolific.com'); # 2094416, 2093620\nSELECT * FROM contacts WHERE id = 6284931;\n\nSELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id\nWHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;\n\nselect * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);\nselect * from crm_configurations where id = 1;\n\n43801692-1aeb-32ce-acba-5b80a479701a\n44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b\n405975c0-b3d0-7aaa-821f-09d59cae6dd1\n4caf848d-4bed-2299-b248-7788d41f9fca\n49bedc3f-f196-eef3-89c3-dea6a3b4aa63\n43420989-a09d-b8f8-9806-c8bbf7a02aac\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nSELECT * FROM activities WHERE id = 75461988;\n\nSELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;\n\nselect * from contacts where id = 17900517;\n\nselect * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id\nwhere crm.provider != 'salesforce';\n\nselect * from users where id = 21047;\nSELECT * FROM crm_configurations WHERE id = 892;\nSELECT * FROM teams WHERE id = 942;\nselect * from opportunities where team_id = 942 order by updated_at desc;\nselect * from contacts where team_id = 942 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 942 and sa.provider = 'hubspot';\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430\nSELECT * FROM crm_configurations WHERE id = 1;\nSELECT * FROM teams WHERE crm_id = 1;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nselect id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1\nSELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430\n\nselect * from teams where id = 852;\nselect * from groups where id = 2286;\nselect * from sidekick_settings where team_id = 852;\nselect * from default_activity_types where team_id = 852;\n\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1 AND u.deleted_at IS NULL\nAND u.crm_required = 1\nAND u.team_id = 1\nORDER BY u.team_id;\n\nSELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (\n18481\n );\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1\n AND u.deleted_at IS NULL\n AND u.crm_required = 1\n# AND u.team_id = 1\n AND p.id IS NULL -- Move this condition to WHERE clause\nORDER BY u.team_id;\n\nSELECT * FROM opportunities WHERE id = 20002609;\nselect * from teams where id = 1122; # Velatir, 29953 - christian@velatir.com\nselect * from crm_configurations where id = 1060;\nselect * from crm_layouts where crm_configuration_id = 1060;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1122 and sa.provider = 'hubspot';\nselect * from opportunities where team_id = 1122 order by updated_at desc;\n\nselect * from crm_field_data where object_type = 'contact';\n\nSELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 248 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS\nSELECT * FROM users where id = 24115;\nSELECT * FROM accounts where id = 4002896;\nSELECT * FROM teams WHERE name LIKE '%adswerve%';\nSELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN (\"0069N000003GIQ9QAO\",\"0061r000019yGP9AAM\",\"0066900001S2KWlAAN\",\"0066900001TDpj2AAD\",\"0066900001b8uEwAAI\",\"0069N000001rQi0QAE\",\"006QF00000KD40mYAD\",\"006QF00000LzpRJYAZ\",\"0069N000002uomtQAA\",\"0069N000002xlMLQAY\",\"0066900001NV6ubAAD\",\"0061r00001HJp45AAD\",\"006QF00000uTlUoYAK\",\"006QF00000v0bZqYAI\");\nSELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203\n\nSELECT u.id, u.email, ac.name, a.* FROM activities a\nJOIN users u ON a.user_id = u.id\nJOIN accounts ac ON a.account_id = ac.id\nWHERE\nuuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or\nuuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or\nuuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;\n\nselect * from users where id = 5825;\nSELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;\n\nselect * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;\n19594, 862\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 862 and sa.provider = 'salesforce';\n\nselect * from automated_reports where id = 36;\nselect ar.frequency, r.*, ar.* from automated_report_results r\njoin automated_reports ar on r.report_id = ar.id\nwhere ar.frequency != 'one_off';\n\nselect s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;\nselect * from nudges n where n.activity_search_id\n\nselect * from teams where created_at > '2026-03-09';\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;\n\nselect * from users where team_id = 1 and name like '%Lukas%'; # 7160\n\nSELECT * FROM teams WHERE id = 575;\nselect * from opportunities where team_id = 575;\nSELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,\nselect * from opportunities where team_id = 1126;\nSELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,\nselect * from opportunities where team_id = 1125;\nselect * from contacts c\nwhere c.team_id = 882;\n\nSELECT * FROM activities WHERE id = 76822967;\nSELECT * FROM crm_profiles WHERE user_id = 15440;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 555;\nSELECT * FROM crm_configurations WHERE id = 555;\nSELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 581 and sa.provider = 'salesforce';\n\nSELECT * FROM automated_report_results order by id desc;\n\nselect * from features;\nselect * from team_features where feature_id = 40;\n\nselect * from teams where id = 556;\n\nselect * from automated_reports;\nwhere id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , [\"pdf\",\"podcast\"]\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\nselect * from automated_report_results order by id desc;\nSELECT * FROM automated_report_results WHERE id = 1919;\n\nselect * from automated_report_results WHERE report_id = 54;\n\nselect * from opportunities where id = 7594349;\n\nSELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - jiminnyintegration@lesmills.com\nselect * from playbooks where team_id = 711; # event 226147\nSELECT * FROM playbook_categories WHERE playbook_id = 5515;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';\nSELECT * FROM crm_fields WHERE id = 226147;\nSELECT * FROM crm_field_values WHERE crm_field_id = 226147;\n\nSELECT * FROM crm_configurations WHERE id = 692;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 711 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;\n\nselect * from leads;\n\nselect * from calendars;\n\nSELECT\n t.id AS team_id,\n t.name,\n LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain\nFROM teams t\nJOIN users u ON u.team_id = t.id\nJOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'\nLEFT JOIN team_domains td\n ON td.team_id = t.id\n AND td.deleted_at IS NULL\n AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))\nGROUP BY t.id, t.name, calendar_domain\nORDER BY t.name, calendar_domain;\n\nselect * from users u join calendars c on c.user_id = u.id\nwhere u.team_id = 882;\n\n\nselect * from activities where id = 74049485; # team 563 crm 537\nselect * from activities where id = 73272382; # team 563 crm 537\nselect * from activities where id = 64400389; # team 563 crm 537\nselect * from activities where id = 58081273; # team 563 crm 537\nselect * from activities where id = 54520297; # team 563 crm 537\nselect * from participants where activity_id = 58081273;\n\nselect * from activities where crm_configuration_id = 537 and provider = 'aircall'\nand account_id = 19003658 order by updated_at desc;\n\nselect * from contacts where crm_configuration_id = 537 and id = 35957759;\nselect * from accounts where crm_configuration_id = 537 and id = 19003658;\n\nselect * from automated_report_results where id = 1976;\nselect * from automated_reports where id = 583;\nselect * from activity_searches where id = 87714;\nselect * from activity_search_filters where activity_search_id = 87714;\n\nSELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid\nor uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot';\nselect * from rate_limits;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2\nand id IN (18, 1872);\nselect * from automated_reports where id = 54;\nSELECT * FROM users WHERE id IN (24623,29443,29613);\n\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\n\nselect * from text_relays where created_at > '2026-05-01';\nand id IN (32415, 32416);\n# and id = 32412;\n\nselect * from users where team_id = 2 and email like '%scott%' and id = 29510;\n\nSELECT * FROM activities WHERE uuid_to_bin('67cebfc2-ed56-44a2-8c68-7a0286ed8618') = uuid; # 79763436\n\nSELECT email_provider_id, COUNT(*) as count, GROUP_CONCAT(id) as ids, GROUP_CONCAT(status) as statuses\nFROM text_relays\nWHERE email_provider_id IN ('19e2027868a64b42', '19e2033ed8ea6b10')\nGROUP BY email_provider_id;\nSELECT id, status, telephony_provider_id, created_at\nFROM activities\nWHERE id IN (80028719, 80028846);\nSELECT id, status, code, email_sent_at, created_at, updated_at\nFROM text_relays\nWHERE id IN (32415, 32416);\nSELECT id, status, code, sender, recipient, created_at\nFROM text_relays\nWHERE sender LIKE '%mario.georgiev%' OR sender LIKE '%stoyan.tomov%'\nORDER BY created_at DESC\nLIMIT 10;\n\nSELECT id, uuid, status, code, sender, recipient, created_at, updated_at\nFROM text_relays\nWHERE uuid = uuid_to_bin('0626141c-27a6-4d8c-aff8-7c8020a2c656');\n\n# ***************\nSELECT DISTINCT u.id, u.email, u.name, u.softphone_number, COUNT(a.id) as sms_count\nFROM users u\nINNER JOIN activities a ON u.id = .user_id\nWHERE a.type LIKE 'sms%'\nAND a.created_at > DATE_SUB(NOW(), INTERVAL 30 DAY)\nGROUP BY u.id, u.email, u.name, u.softphone_number\nORDER BY sms_count DESC;\n\nselect * from teams where id = 1;\n\nselect * from roles;\n\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1117 and sa.provider = 'hubspot';\nSELECT * FROM activities WHERE uuid_to_bin('8024fffb-2df7-4017-91f4-d9f896050248') = uuid; # 79933459 YES\nSELECT * FROM activities WHERE uuid_to_bin('25529043-8094-4781-927f-4f4da2a8185c') = uuid; # 80186192 NO\nSELECT * FROM crm_configurations WHERE id = 1053;\nSELECT * FROM teams WHERE id = 1117;\nselect * from users where id = 30249;\nselect * from playbooks where id = 5473;\nselect * from playbook_categories where id = 43783;\nselect * from playbook_categories where playbook_id = 5473;\nselect * from crm_fields where id = 659242;\nselect * from crm_field_values where crm_field_id = 659242;\n\nSELECT * FROM crm_field_data fd\n# JOIN crm_fields f ON fd.crm_field_id = f.id\n# JOIN activities a ON fd.activity_id = a.id\nWHERE activity_id = 79933459\n# AND f.crm_provider_id = 'hs_activity_type';\n\n\nSELECT * FROM activity_messages;\nselect * from text_relays where created_at > '2026-05-01';\nselect * from activities where user_id IN (7160, 18608) and created_at > '2026-05-22' order by id desc;\nselect * from users where team_id = 1 and id IN (18608, 13934, 7160);\nselect * from activities where user_id = 7160 order by id desc limit 10;\n\nselect * from accounts where team_id = 1 and name = 'Column5';\n\nselect * from users where name like '%Subra%'; # 31054, 1117\nselect * from teams where id = 1117;\nselect * from activity_searches where user_id = 31054;\nselect * from activity_search_filters where activity_search_id IN (88882, 88902);","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-4379827447387526057
|
1137771414947247693
|
typing_pause
|
accessibility
|
NULL
|
Project: faVsco.js, menu
#12121 on JY-20963-fix-im Project: faVsco.js, menu
#12121 on JY-20963-fix-import-on-deleted-entity, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Hubspot\Journal;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
use Jiminny\Models\Team;
use Jiminny\Repositories\Crm\CrmConfigurationRepository;
use Jiminny\Repositories\TeamRepository;
use Jiminny\Services\Crm\Hubspot\Webhook\WebhookEventProcessor;
class HubspotJournalPollingService
{
private const string [ENV_SECRET];
private const string [ENV_SECRET];
private const string [ENV_SECRET];
private const int LOCK_TTL_SECONDS = 120; // 2 minutes - renewed every 30 seconds
private const int LOCK_RENEWAL_INTERVAL = 30; // Renew lock every 30 seconds
private const int BASE_SLEEP_SECONDS = 5; // Base sleep when no data
private const int MAX_SLEEP_SECONDS = 120; // Maximum sleep duration
private const int EMPTY_THRESHOLD_FOR_BACKOFF = 3; // Empty results before increasing sleep
private const int MAX_CYCLES_DEFAULT = 3000; // Default maximum cycles before stopping
private const int MEMORY_CRITICAL_THRESHOLD = 90; // 90% of memory limit
private const int MAX_BACKOFF_SECONDS = 300;
private const int MAX_OFFSET_RETRIES = 3;
private const int MAX_RUNTIME_SECONDS = 240; // 4 minutes
private const int MAX_EMPTY_RESULTS_BEFORE_EXIT = 5;
private const int LOG_INTERVAL_CYCLES = 10;
private bool $shouldStop = false;
private int $consecutiveEmptyResults = 0;
private array $offsetRetryCount = [];
private int $cycleCount = 0;
private int $startTime = 0;
private int $lastLockRenewal = 0;
private float $totalApiTime = 0;
private float $totalDownloadTime = 0;
private float $totalTransformTime = 0;
private float $totalProcessTime = 0;
private int $totalJournalFilesDownloaded = 0;
private int $totalEventsProcessed = 0;
private int $emptyJournalFiles = 0;
private int $otherPortalSkipped = 0;
public function __construct(
private HubspotJournalApiClient $apiClient,
private JournalEventTransformer $transformer,
private WebhookEventProcessor $eventProcessor
) {
}
/**
* Start continuous polling of the HubSpot journal
*/
public function startPolling(): void
{
$this->startTime = time();
$this->cycleCount = 0;
$this->logPollingStart();
if (! $this->acquirePollingLock()) {
Log::warning('[HubSpot Journal Polling] Another polling process is already running');
return;
}
try {
while ($this->shouldContinuePolling()) {
$this->cycleCount++;
$this->executePollingCycle();
}
} catch (\Throwable $e) {
Log::error('[HubSpot Journal Polling] Error while polling', [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
]);
} finally {
$this->cleanupPollingSession();
}
}
/**
* Perform a single polling cycle
* Returns true if work was found and processed, false if no work available, null if entry was skipped
*/
public function pollOnce(): ?bool
{
$currentOffset = $this->getCurrentOffset();
$apiStart = microtime(true);
$apiResult = $currentOffset === null
? $this->apiClient->getLatestJournalEntry()
: $this->apiClient->getNextJournalEntry($currentOffset);
$this->totalApiTime += (microtime(true) - $apiStart) * 1000;
if (! $apiResult->success) {
return $this->handleApiResult($apiResult, $currentOffset ?? 'latest');
}
if ($apiResult->data === null) {
Log::info('[HubSpot Journal Polling] No data');
return false;
}
$offset = $apiResult->data['currentOffset'];
$s3Url = $apiResult->data['url'];
$retryCount = $this->offsetRetryCount[$offset] ?? 0;
$downloadStart = microtime(true);
$downloadResult = $this->apiClient->downloadJournalFile($s3Url);
$this->totalDownloadTime += (microtime(true) - $downloadStart) * 1000;
if (! $downloadResult->success) {
return $this->handleDownloadResult($downloadResult, $offset, $retryCount);
}
$this->totalJournalFilesDownloaded++;
$journalData = $downloadResult->data;
$transformStart = microtime(true);
try {
$transformedEvents = $this->transformer->transformJournalEvents($journalData);
} catch (\Exception $e) {
return $this->handleTransformationFailure($offset, $retryCount, $e);
}
$this->totalTransformTime += (microtime(true) - $transformStart) * 1000;
unset($journalData);
$processStart = microtime(true);
$eventsCount = count($transformedEvents);
$this->totalEventsProcessed += $eventsCount;
if ($eventsCount === 0) {
$this->emptyJournalFiles++;
} else {
$this->eventProcessor->processEvents($transformedEvents, '[HubSpot Journal Polling]');
}
$this->totalProcessTime += (microtime(true) - $processStart) * 1000;
$this->updateOffset($offset);
unset($transformedEvents);
$this->logProgressIfNeeded();
return $eventsCount > 0;
}
private function logProgressIfNeeded(): void
{
if ($this->cycleCount === 0 || $this->cycleCount % self::LOG_INTERVAL_CYCLES !== 0) {
return;
}
$cycles = $this->cycleCount;
$avgTotal = ($this->totalApiTime + $this->totalDownloadTime + $this->totalTransformTime + $this->totalProcessTime) / $cycles;
Log::info('[HubSpot Journal Polling] Progress', [
'cycles' => $cycles,
'files' => $this->totalJournalFilesDownloaded,
'events' => $this->totalEventsProcessed,
'empty_files' => $this->emptyJournalFiles,
'avg_ms' => round($avgTotal, 1),
'avg_api_ms' => round($this->totalApiTime / $cycles, 1),
'avg_download_ms' => round($this->totalDownloadTime / $cycles, 1),
'avg_transform_ms' => round($this->totalTransformTime / $cycles, 1),
'avg_process_ms' => round($this->totalProcessTime / $cycles, 1),
]);
}
/**
* Get the current polling offset from Redis
*/
private function getCurrentOffset(bool $cacheOnly = false): ?string
{
$offset = Redis::get(self::OFFSET_CACHE_KEY);
if (! $offset && ! $cacheOnly) {
$offset = $this->getDbOffset();
}
return $offset ? (string) $offset : null;
}
/**
* Get the last stored offset from the database
*/
public function getDbOffset(): ?string
{
$jiminnyTeam = $this->getJiminnyTeam();
if (! $jiminnyTeam instanceof Team) {
Log::error('[HubSpot Journal Polling] Jiminny team not found');
return null;
}
$crmRepository = app(CrmConfigurationRepository::class);
$offset = $crmRepository->getSetting($jiminnyTeam->getCrmConfiguration(), 'hubspot_journal_offset');
Log::info('[HubSpot Journal Polling] Getting offset from database', [
'offset' => $offset,
'jiminny_team_id' => $jiminnyTeam->getId(),
]);
return $offset;
}
/**
* Reset the database offset
*/
public function resetDbOffset(): void
{
$jiminnyTeam = $this->getJiminnyTeam();
if (! $jiminnyTeam instanceof Team) {
Log::error('[HubSpot Journal Polling] Jiminny team not found');
return;
}
$crmRepository = app(CrmConfigurationRepository::class);
$crmRepository->updateSetting($jiminnyTeam->getCrmConfiguration(), 'hubspot_journal_offset', '');
Log::info('[HubSpot Journal Polling] Database offset reset');
}
private function getJiminnyTeam(): ?Team
{
$teamRepository = app(TeamRepository::class);
return $teamRepository->getTeamBySlug('jiminny');
}
private function updateDbOffset(string $offset): void
{
$jiminnyTeam = $this->getJiminnyTeam();
if (! $jiminnyTeam instanceof Team) {
Log::error('[HubSpot Journal Polling] Jiminny team not found');
return;
}
$crmRepository = app(CrmConfigurationRepository::class);
$crmRepository->updateSetting($jiminnyTeam->getCrmConfiguration(), 'hubspot_journal_offset', $offset);
}
/**
* Update the polling offset
*/
private function updateOffset(string $offset): void
{
Redis::setex(self::OFFSET_CACHE_KEY, 259200, $offset); // 3 days TTL
$this->clearOffsetRetryCount($offset);
}
/**
* Reset the polling offset
*/
public function resetOffset(): void
{
Redis::del(self::OFFSET_CACHE_KEY);
Log::info('[HubSpot Journal Polling] Reset polling offset');
}
/**
* Set a specific offset (for manual override or recovery)
*/
public function setOffset(string $offset): void
{
$this->updateOffset($offset);
Log::warning('[HubSpot Journal Polling] Offset manually set', [
'offset' => $offset,
]);
}
/**
* Get current polling status
*/
public function getPollingStatus(): array
{
$lockDataJson = Redis::get(self::POLLING_LOCK_KEY);
$lockData = $lockDataJson ? json_decode($lockDataJson, true) : null;
return [
'is_locked' => $lockData !== null,
'current_offset' => $this->getCurrentOffset(),
'lock_expires_at' => $lockData['expires_at'] ?? null,
'lock_acquired_at' => $lockData['acquired_at'] ?? null,
];
}
/**
* Acquire exclusive polling lock to prevent multiple instances
*/
private function acquirePollingLock(): bool
{
$expiresAt = now()->addSeconds(self::LOCK_TTL_SECONDS)->toISOString();
// Use atomic operation to set both lock and expiration data
$lockData = [
'locked' => true,
'expires_at' => $expiresAt,
'acquired_at' => now()->toISOString(),
];
// Use SETNX (SET if Not eXists) for atomic lock acquisition
$lockAcquired = Redis::set(self::POLLING_LOCK_KEY, json_encode($lockData), 'EX', self::LOCK_TTL_SECONDS, 'NX');
if ($lockAcquired) {
$this->lastLockRenewal = time();
Log::info('[HubSpot Journal Polling] Acquired polling lock', [
'expires_at' => $expiresAt,
]);
}
return (bool) $lockAcquired;
}
/**
* Release the polling lock
*/
private function releasePollingLock(): void
{
Redis::del(self::POLLING_LOCK_KEY);
Log::info('[HubSpot Journal Polling] Released polling lock');
}
/**
* Force release the polling lock (for emergency situations)
*/
public function forceReleaseLock(): void
{
$this->releasePollingLock();
Log::warning('[HubSpot Journal Polling] Force released polling lock');
}
/**
* Signal the polling service to stop gracefully
*/
public function requestStop(): void
{
Redis::setex(self::STOP_FLAG_KEY, 300, '1'); // 5 minutes TTL
$this->shouldStop = true;
Log::info('[HubSpot Journal Polling] Stop requested');
}
/**
* Check if polling should stop
*/
private function shouldStop(): bool
{
// Check local flag first (faster)
if ($this->shouldStop) {
return true;
}
// Check Redis flag (for external stop requests)
if (Redis::exists(self::STOP_FLAG_KEY)) {
$this->shouldStop = true;
return true;
}
return false;
}
/**
* Clear the stop flag and reset state to allow service to start
*/
public function clearStopFlag(): void
{
Redis::del(self::STOP_FLAG_KEY);
$this->shouldStop = false;
$this->resetPollingState();
Log::info('[HubSpot Journal Polling] Stop flag cleared and state reset');
}
/**
* Reset polling state without clearing stop flag
*/
private function resetPollingState(): void
{
$this->consecutiveEmptyResults = 0;
$this->cycleCount = 0;
$this->startTime = 0;
$this->totalApiTime = 0;
$this->totalDownloadTime = 0;
$this->totalTransformTime = 0;
$this->totalProcessTime = 0;
$this->totalJournalFilesDownloaded = 0;
$this->totalEventsProcessed = 0;
$this->emptyJournalFiles = 0;
$this->otherPortalSkipped = 0;
}
public function hasStopFlag(): bool
{
return (bool) Redis::exists(self::STOP_FLAG_KEY);
}
/**
* Calculate adaptive sleep duration based on consecutive empty results
*/
private function calculateAdaptiveSleep(): int
{
if ($this->consecutiveEmptyResults < self::EMPTY_THRESHOLD_FOR_BACKOFF) {
return self::BASE_SLEEP_SECONDS; // 5 second
}
// Progressive backoff: 15s -> 30s -> 60s -> 120s (max)
$delay = 3 * self::BASE_SLEEP_SECONDS;
$sleepDuration = $delay * (2 ** ($this->consecutiveEmptyResults - self::EMPTY_THRESHOLD_FOR_BACKOFF));
return min($sleepDuration, self::MAX_SLEEP_SECONDS);
}
private function logPollingStart(): void
{
Log::info('[HubSpot Journal Polling] Service starting', [
'memory_limit' => ini_get('memory_limit'),
'max_execution_time' => ini_get('max_execution_time'),
'initial_memory_mb' => round(memory_get_usage(true) / 1024 / 1024, 2),
]);
}
/**
* Log polling service end information
*/
private function logPollingEnd(): void
{
$runtime = time() - $this->startTime;
$cycles = max($this->cycleCount, 1);
Log::info('[HubSpot Journal Polling] Service ending', [
'runtime_seconds' => $runtime,
'total_cycles' => $this->cycleCount,
'files_downloaded' => $this->totalJournalFilesDownloaded,
'empty_files' => $this->emptyJournalFiles,
'other_portal_skipped' => $this->otherPortalSkipped,
'total_events' => $this->totalEventsProcessed,
'events_per_file' => $this->totalJournalFilesDownloaded > 0
? round($this->totalEventsProcessed / $this->totalJournalFilesDownloaded, 1)
: 0,
'avg_api_ms' => round($this->totalApiTime / $cycles, 1),
'avg_download_ms' => round($this->totalDownloadTime / $cycles, 1),
'avg_transform_ms' => round($this->totalTransformTime / $cycles, 1),
'avg_process_ms' => round($this->totalProcessTime / $cycles, 1),
'peak_memory_mb' => round(memory_get_peak_usage(true) / 1024 / 1024, 2),
]);
}
/**
* Improved stop condition check with clear reasoning
*/
private function shouldContinuePolling(): bool
{
// Check explicit stop request first (fastest check)
if ($this->shouldStop()) {
Log::info('[HubSpot Journal Polling] Stop requested, ending polling');
return false;
}
if ($this->consecutiveEmptyResults >= self::MAX_EMPTY_RESULTS_BEFORE_EXIT) {
Log::warning('[HubSpot Journal Polling] Maximum empty results reached, stopping', [
'empty_results' => $this->consecutiveEmptyResults,
'max_empty_results' => self::MAX_EMPTY_RESULTS_BEFORE_EXIT,
]);
return false;
}
// Check runtime limit (4 minutes)
$runtime = time() - $this->startTime;
if ($runtime >= self::MAX_RUNTIME_SECONDS) {
Log::warning('[HubSpot Journal Polling] Maximum runtime reached, stopping', [
'runtime_seconds' => $runtime,
'runtime_minutes' => round($runtime / 60, 1),
'max_runtime_seconds' => self::MAX_RUNTIME_SECONDS,
]);
return false;
}
// Check memory limits (prevent OOM)
$currentMemory = memory_get_usage(true);
$memoryLimitBytes = $this->parseMemoryLimit(ini_get('memory_limit'));
if ($memoryLimitBytes > 0 && $currentMemory > ($memoryLimitBytes * self::MEMORY_CRITICAL_THRESHOLD / 100)) {
Log::warning('[HubSpot Journal Polling] Memory limit approaching, stopping', [
'current_memory_mb' => round($currentMemory / 1024 / 1024, 2),
'memory_limit' => ini_get('memory_limit'),
'usage_percent' => round(($currentMemory / $memoryLimitBytes) * 100, 1),
]);
return false;
}
// Check for excessive cycles (prevent runaway processes)
if ($this->cycleCount > self::MAX_CYCLES_DEFAULT) {
Log::warning('[HubSpot Journal Polling] Maximum cycles reached, stopping', [
'cycles' => $this->cycleCount,
'max_cycles' => self::MAX_CYCLES_DEFAULT,
]);
return false;
}
return true;
}
/**
* Handle when work is found - reset counters and continue immediately
*/
private function handleWorkFound(): void
{
$this->consecutiveEmptyResults = 0;
}
/**
* Handle when no work is found - implement adaptive sleep
*/
private function handleNoWorkFound(): void
{
$this->consecutiveEmptyResults++;
$sleepDuration = $this->calculateAdaptiveSleep();
Log::debug('[HubSpot Journal Polling] No work found, sleeping', [
'consecutive_empty' => $this->consecutiveEmptyResults,
'sleep_seconds' => $sleepDuration,
'cycle' => $this->cycleCount,
]);
$this->responsiveSleep($sleepDuration);
}
/**
* Sleep with responsive stop checking
*/
private function responsiveSleep(int $seconds): void
{
for ($i = 0; $i < $seconds && $this->shouldContinuePolling(); $i++) {
sleep(1);
}
}
/**
* Parse memory limit string to bytes
*/
private function parseMemoryLimit(string $memoryLimit): int
{
if ($memoryLimit === '-1') {
return 0; // Unlimited
}
$unit = strtolower(substr($memoryLimit, -1));
$value = (int) substr($memoryLimit, 0, -1);
return match ($unit) {
'g' => $value * 1024 * 1024 * 1024,
'm' => $value * 1024 * 1024,
'k' => $value * 1024,
default => (int) $memoryLimit,
};
}
private function executePollingCycle(): void
{
$this->renewLockIfNeeded();
$result = $this->pollOnce();
if ($result === true) {
$this->handleWorkFound();
} elseif ($result === false) {
$this->handleNoWorkFound();
}
}
private function renewLockIfNeeded(): void
{
$now = time();
if ($now - $this->lastLockRenewal >= self::LOCK_RENEWAL_INTERVAL) {
$this->renewPollingLock();
$this->lastLockRenewal = $now;
}
}
private function renewPollingLock(): void
{
$expiresAt = now()->addSeconds(self::LOCK_TTL_SECONDS)->toISOString();
$lockData = [
'locked' => true,
'expires_at' => $expiresAt,
'acquired_at' => now()->toISOString(),
'renewed_at' => now()->toISOString(),
'cycle' => $this->cycleCount,
];
Redis::setex(self::POLLING_LOCK_KEY, self::LOCK_TTL_SECONDS, json_encode($lockData));
Log::debug('[HubSpot Journal Polling] Lock renewed', [
'expires_at' => $expiresAt,
'cycle' => $this->cycleCount,
]);
}
private function handleApiResult(JournalApiResult $result, string $context): bool
{
if ($result->failureType === JournalApiResult::FAILURE_AUTH) {
Log::warning('[HubSpot Journal Polling] Auth failure, will retry next cycle', [
'context' => $context,
]);
return false;
}
if ($result->failureType === JournalApiResult::FAILURE_RATE_LIMIT) {
$waitSeconds = min($result->retryAfterSeconds ?? 60, self::MAX_BACKOFF_SECONDS);
Log::warning('[HubSpot Journal Polling] Rate limit hit, waiting', [
'wait_seconds' => $waitSeconds,
]);
$this->responsiveSleep($waitSeconds);
return false;
}
if ($result->failureType === JournalApiResult::FAILURE_OFFSET_EXPIRED) {
Log::warning('[HubSpot Journal Polling] Offset expired, resetting to fetch latest data', [
'expired_offset' => $context,
]);
$this->resetOffset();
$this->resetDbOffset();
return false;
}
if ($result->isPermanentFailure()) {
Log::error('[HubSpot Journal Polling] Permanent API failure', [
'context' => $context,
'failure_type' => $result->failureType,
'error' => $result->errorMessage,
]);
$this->shouldStop = true;
return false;
}
Log::warning('[HubSpot Journal Polling] Retryable API failure', [
'context' => $context,
'failure_type' => $result->failureType,
'error' => $result->errorMessage,
]);
if ($result->retryAfterSeconds) {
sleep(min($result->retryAfterSeconds, self::MAX_BACKOFF_SECONDS));
}
return false;
}
/**
* Clean up polling session resources
*/
private function cleanupPollingSession(): void
{
$this->logPollingEnd();
$this->storeOffsetInDB();
$this->releasePollingLock();
$this->apiClient->clearPortalCache();
$this->resetPollingState();
}
private function storeOffsetInDB(): void
{
// Save current offset to database before cleanup
$currentOffset = $this->getCurrentOffset(cacheOnly: true);
if ($currentOffset) {
$this->updateDbOffset($currentOffset);
Log::info('[HubSpot Journal Polling] Saved offset to database on cleanup', [
'offset' => $currentOffset,
]);
}
}
private function handleDownloadResult(JournalApiResult $result, string $offset, int $retryCount): ?bool
{
if ($result->failureType === JournalApiResult::FAILURE_UNKNOWN_PORTAL) {
$this->otherPortalSkipped++;
$this->updateOffset($offset);
return null;
}
if ($result->isPermanentFailure()) {
Log::warning('[HubSpot Journal Polling] Permanent failure, skipping offset', [
'offset' => $offset,
'portal_id' => $result->portalId,
'failure_type' => $result->failureType,
'error' => $result->errorMessage,
]);
$this->updateOffset($offset);
$this->clearOffsetRetryCount($offset);
return false;
}
$retryCount++;
if ($retryCount >= self::MAX_OFFSET_RETRIES) {
Log::error('[HubSpot Journal Polling] Max retries reached, skipping offset', [
'offset' => $offset,
'portal_id' => $result->portalId,
'failure_type' => $result->failureType,
'retry_count' => $retryCount,
]);
$this->updateOffset($offset);
$this->clearOffsetRetryCount($offset);
return false;
}
Log::warning('[HubSpot Journal Polling] Retryable failure, will retry', [
'offset' => $offset,
'failure_type' => $result->failureType,
'retry_count' => $retryCount,
'max_retries' => self::MAX_OFFSET_RETRIES,
]);
$this->offsetRetryCount[$offset] = $retryCount;
if ($result->retryAfterSeconds) {
sleep(min($result->retryAfterSeconds, self::MAX_BACKOFF_SECONDS));
}
return false;
}
/**
* Handle transformation failure with retry logic
*/
private function handleTransformationFailure(string $offset, int $retryCount, \Exception $exception): bool
{
$retryCount++;
if ($retryCount >= self::MAX_OFFSET_RETRIES) {
Log::critical('[HubSpot Journal Polling] Max transformation retries reached - SKIPPING offset', [
'offset' => $offset,
'retry_count' => $retryCount,
'error' => $exception->getMessage(),
'trace' => $exception->getTraceAsString(),
]);
// Skip this offset to prevent infinite loop with corrupted data
$this->updateOffset($offset);
$this->clearOffsetRetryCount($offset);
return false;
}
Log::error('[HubSpot Journal Polling] Transformation failed - will retry', [
'offset' => $offset,
'retry_count' => $retryCount,
'max_retries' => self::MAX_OFFSET_RETRIES,
'error' => $exception->getMessage(),
]);
$this->offsetRetryCount[$offset] = $retryCount;
return false;
}
/**
* Clear retry count for an offset after successful processing
*/
private function clearOffsetRetryCount(string $offset): void
{
unset($this->offsetRetryCount[$offset]);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
45
1
41
66
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993
SELECT * FROM users WHERE id = 25061;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 994;
SELECT * FROM crm_profiles WHERE user_id = 25061;
select * from crm_configurations where id = 834;
SELECT * FROM teams WHERE id = 882;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;
SELECT * FROM contacts where crm_configuration_id = 834;
SELECT * FROM opportunities WHERE team_id = 933
# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');
AND id IN (8482561,18352941,19042734,19232139,19445140,19472541);
SELECT * FROM opportunity_contacts
WHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 485; #
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
select crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id
where crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')
# and l.converted_at IS NOT NULL
;
# [PASSWORD_DOTS]
SELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')
and opportunity_id IS NULL
order by id desc;
SELECT * FROM teams WHERE id = 604; # 598
SELECT * FROM activities WHERE id = 74410828; # [EMAIL]
SELECT * FROM accounts WHERE id = 20068382;
SELECT * FROM accounts WHERE id = 35186038;
SELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 559 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;
select * from sidekick_settings where team_id = 781;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100
SELECT * FROM crm_layouts WHERE crm_configuration_id = 711;
SELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL
and is_internal = 0 and status = 'completed'
order by id desc;
SELECT * FROM crm_layout_entities
WHERE crm_layout_id IN (2352, 2353);
;
SELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 556 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;
SELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;
select * from contacts
where crm_configuration_id = 530
and crm_provider_id = 872252;
select * from activities where crm_configuration_id = 530
and user_id = 14343 and type like '%softphone%'
and created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);
SELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t
JOIN crm_configurations c ON t.id = c.team_id
WHERE t.status = 'active';
SELECT * FROM teams where id = 1091;
SELECT * FROM crm_configurations where team_id = 1091;
SELECT * FROM activity_providers where team_id = 1091;
SELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT * FROM teams WHERE name LIKE '%Leadventure%';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1091 and sa.provider = 'salesforce';
SELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812
SELECT * FROM teams where id = 862;
SELECT * FROM crm_configurations where team_id = 862;
SELECT * FROM activity_providers where team_id = 862;
SELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT t.id, crm.id, crm.provider, ap.* FROM teams t
join crm_configurations crm on t.id = crm.team_id
join activity_providers ap on t.id = ap.team_id
where t.status = 'active' and ap.is_enabled = 1
and crm.provider = 'hubspot'
and ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',
'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');
SELECT * FROM teams where id = 1068;
SELECT * FROM crm_configurations where team_id = 1068;
SELECT * FROM activity_providers where team_id = 1068;
SELECT * FROM activities a
where crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')
and a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'
)
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by a.id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1068 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262
SELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
select * from crm_layouts where crm_configuration_id = 834;
select * from crm_layout_entities where crm_layout_id = 2780;
select * from crm_fields where id IN (321153,321192,321193,321194);
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1057 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8
SELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20
SELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10
SELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #
SELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;
select * from users where team_id = 51; # 7783
SELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130
select * from activity_searches where user_id = 7783;
select * from activity_search_filters where activity_search_id IN (32291, 32292);
SELECT asf.activity_search_id, asf.id, asf.value
FROM activity_search_filters asf
WHERE asf.filter = 'group_id'
AND asf.value IN (
SELECT CONCAT(
HEX(SUBSTR(uuid, 5, 4)), '-',
HEX(SUBSTR(uuid, 3, 2)), '-',
HEX(SUBSTR(uuid, 1, 2)), '-',
HEX(SUBSTR(uuid, 9, 2)), '-',
HEX(SUBSTR(uuid, 11))
)
FROM groups
WHERE deleted_at IS NOT NULL
);
SELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where provider = 'hubspot';
SELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133
SELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null
# [PASSWORD_DOTS]
select * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';
select
cp.*
# DISTINCT t.id
# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields
FROM crm_profiles cp
JOIN crm_configurations crm on crm.id = cp.crm_configuration_id
JOIN users u on u.id = cp.user_id
JOIN teams t ON t.id = crm.team_id
WHERE crm.provider = 'salesforce' and t.status = 'active'
and cp.archived_at IS NULL and u.deleted_at IS NULL
and t.id NOT IN (1093)
and t.id = 2
and cp.contact_fields IS NULL;
# and c.crm_provider_id = '003Uu00000ojD4NIAU';
SELECT * FROM users WHERE id = 26484;
SELECT * FROM crm_profiles WHERE user_id = 26484;
SELECT * FROM social_accounts WHERE sociable_id = 26484;
SELECT * FROM crm_configurations where provider = 'salesforce';
select * from users where id IN (10022, 10403);
select * from users where team_id IN (526);
select * from teams where id IN (526, 532);
select * from crm_configurations where id IN (500, 516);
select * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);
select * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 526 and sa.provider = 'salesforce';
select * from team_settings where team_id IN (526, 532);
select * from users where id IN (22824);
select * from crm_profiles where crm_configuration_id IN (1026);
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1093 and sa.provider = 'salesforce';
select * from teams where id = 1099;
select * from users where id = 29643
select * from activity_processing_states;
SELECT * FROM teams where name LIKE '%Fare%'; # 233
SELECT * FROM opportunities where crm_configuration_id = 215
# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'
;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1088 and sa.provider = 'hubspot';
SELECT * FROM teams order by updated_at DESC
SELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account
select * from crm_configurations where provider = 'pipedrive';
select * from teams where id = 957;
select * from crm_configurations where id = 957;
SELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743
SELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;
select * from users where team_id = 1; # 26726 - Gabriela Dureva
SELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific
select * from activities where user_id = 26726 order by id desc;
select * from contacts where crm_configuration_id = 1
and email IN ('[EMAIL]', '[EMAIL]'); # 2094416, 2093620
SELECT * FROM contacts WHERE id = 6284931;
SELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id
WHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;
select * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);
select * from crm_configurations where id = 1;
43801692-1aeb-32ce-acba-5b80a479701a
44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b
405975c0-b3d0-7aaa-821f-09d59cae6dd1
4caf848d-4bed-2299-b248-7788d41f9fca
49bedc3f-f196-eef3-89c3-dea6a3b4aa63
43420989-a09d-b8f8-9806-c8bbf7a02aac
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
SELECT * FROM activities WHERE id = 75461988;
SELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;
select * from contacts where id = 17900517;
select * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id
where crm.provider != 'salesforce';
select * from users where id = 21047;
SELECT * FROM crm_configurations WHERE id = 892;
SELECT * FROM teams WHERE id = 942;
select * from opportunities where team_id = 942 order by updated_at desc;
select * from contacts where team_id = 942 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 942 and sa.provider = 'hubspot';
SELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430
SELECT * FROM crm_configurations WHERE id = 1;
SELECT * FROM teams WHERE crm_id = 1;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1 and sa.provider = 'salesforce';
select id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1
SELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430
select * from teams where id = 852;
select * from groups where id = 2286;
select * from sidekick_settings where team_id = 852;
select * from default_activity_types where team_id = 852;
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1 AND u.deleted_at IS NULL
AND u.crm_required = 1
AND u.team_id = 1
ORDER BY u.team_id;
SELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (
18481
);
SELECT cc.provider, cc.id, p.id, u.*
FROM users u
LEFT JOIN crm_profiles p ON u.id = p.user_id
INNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'
INNER JOIN crm_configurations cc ON t.crm_id = cc.id
WHERE u.status = 1
AND u.deleted_at IS NULL
AND u.crm_required = 1
# AND u.team_id = 1
AND p.id IS NULL -- Move this condition to WHERE clause
ORDER BY u.team_id;
SELECT * FROM opportunities WHERE id = 20002609;
select * from teams where id = 1122; # Velatir, 29953 - [EMAIL]
select * from crm_configurations where id = 1060;
select * from crm_layouts where crm_configuration_id = 1060;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1122 and sa.provider = 'hubspot';
select * from opportunities where team_id = 1122 order by updated_at desc;
select * from crm_field_data where object_type = 'contact';
SELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.em...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85263
|
2921
|
11
|
2026-05-28T12:15:57.700171+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970557700_m2.jpg...
|
PhpStorm
|
faVsco.js – HubspotJournalPollingService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
#12121 on JY-20963-fix-im Project: faVsco.js, menu
#12121 on JY-20963-fix-import-on-deleted-entity, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12121 on JY-20963-fix-import-on-deleted-entity, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.11569149,"height":0.025538707},"on_screen":true,"help_text":"Pull request #12121 exists for current branch JY-20963-fix-import-on-deleted-entity","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8374335,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"bounds":{"left":0.85272604,"top":0.019952115,"width":0.062832445,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-5599254006743683834
|
-7050965352302034496
|
typing_pause
|
hybrid
|
NULL
|
Project: faVsco.js, menu
#12121 on JY-20963-fix-im Project: faVsco.js, menu
#12121 on JY-20963-fix-import-on-deleted-entity, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
rnpstomViewPVovsco.s© VoiceConsentPrefix.phpNotificationsv Observers© AccountObserver.phcCActwwooserver.pnp© ContactObserver.phgGroupObserver.pho© LeadObserver.phoC ProfileObserver.phpC SocialAccountObserver.phg© UserObserver.pho© UserRoleObserver.phc> (l PoliciesaProvidersQueueu Reoositoniea RulesvServicesDa ActivityAiReodnimermobiacte@ DecorateActivityDummym Helnarsv m Hibsnd(i) AccountSyncStrategMAetioneMcontdSuncstrateon• D DTO› FieldsThtauendOpportunivsvncstratcov- Pac nation-ProsoecSearchStratco→- RedisService traits• Utils- Wechookc) Batchsunceo ector cho© BatchSvncRedisService.oCleantono@ GiosedDealStanesSeniceclnaalise rccarica onoCoocWindowwnapers.ohOLenkоkyseiwico.onMWiaKorCass wochexe* Breturn T The result of the APi callprivate function executeRequest(callable SapiCall)ScacheKey = Sthis->getRateLimitCacheKeyOScacheotxozresac = keozst.oet scachekey)*if ds string(ScachedExpiresAt)) 8& is numeric(ScachSremaining = naxl vaano scachedhrow new kaceLinzcexcepe.onsrenaining,neruonSantwaittos} catch (Throvable Se)!i4 (Sthiso>isHubsootRateLinit(Se))metnwAttenThisorrarse?erry.trer teNx: oniy the Sinet doh to receive a 420Subseauent 0s in the sane burct leaveIl window is not reset by every concurrentRediceeset(Scachekey. (strino) (eine0) 4 So 319Sthie-slog-smaroino(*[Huhsnotl Recesved 420 32:iteanSdles Sthte-sconfioestean sa 32:'configid'= Sthís-scontsocsoettala 323as Scetryatter= Se->getMessageOthrow new RateLinitException message: "Hubsr S2Throw Senprivate function getRateLinitCachekevO: strinol...;TO0% L7inu co moy to.loro+0.ActivityControlker.thp=custom.logaraveuesA SF fiminny@localhost)HS Jocal (jminny@localhost)okeinuironeA console [STAGINGC) Client.php X php autoload.phgDa00Eind in Files match inathiee maskondSockacquired = Redis"ser seheporuing lock key ison encodcislockoala eXSeRLOCK TTL SECONDS,INXYx5 Cc wIn Project Module Directory Scoped = Redis::set(self:POLLING_LOCK,KEY, Ison_encode(SlockData), "EX, self:LOCK_TTL_SECONDS, HubspotJourna Po ngService.php 319d console (PROD) x C Service.phpds consoeleu.Do jminny v0458185Y0 AEND AS user id1896856248 = UU1d: # 79953459 Y2=4da2a8185c') = uuid: # 80186192 NỎHubspot.JournalPollingService.ohp app/Services/Crm/Hubsoot/JolUse aromic opcration to ser both lock and exotracion daraSlockData =1•ockedexorresn ss seyotres.tacautredar s nomeetoisienaon// Use SETNX (SET if Not eXists) for atonic lock acquisitionSlockAcquired = Redis::set( key: self::POLLING_LOCK_KEY, json_encode(SlockData), optiom"Ex" sole-atnoki sea+SlockAcous cedh$this->lastLockRenewal = tineO:Log: : info( message:'[HubSpot Journal Polling] Acquired polling Lock', daynsnes ati = Seyasresat.ID:return (bool) SlockAcquired:* Release the polZing lockprivate function releasePolZinglockO: voideoen rosutsiin now neeoeninanene oinCacaado CodoxoKick of a new proisct. Make chunoe> *2026-05-22' order by id desc3824889822c. Fix Texikelay service TesteC Multi-Picklist Layout Displatent.ohoat.9om1a,"Pode swioth• oNtwndeurTasme oeii.s...
|
85261
|
NULL
|
NULL
|
NULL
|
|
85261
|
2921
|
10
|
2026-05-28T12:15:54.926050+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970554926_m2.jpg...
|
PhpStorm
|
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Find in Files
29 matches in 8 files
File mask:
*.p Find in Files
29 matches in 8 files
File mask:
*.php
*.php
Auto
*.php
Filter Search Results
Pin Window
Search History
$lockAcquired = Redis::set(self::POLLING_LOCK_KEY, json_encode($lockData), 'EX', self::LOCK_TTL_SECONDS, 'NX');
New Line
Match case
Words
Regex
Replace History
Replace
New Line
Preserve case
In Project
Module
Directory
Scope
Module
/Users/lukas/jiminny/app/app/Services/Crm/Hubspot
/Users/lukas/jiminny/app/app/Services/Crm/Hubspot
/Users/lukas/jiminny/app/app/Console/Commands
/Users/lukas/jiminny/app/tests/Unit/Services/Mail
/Users/lukas/jiminny/app/app/Services/Mail
/Users/lukas/jiminny/app/app/Console
/Users/lukas/jiminny/app/storage/logs
/Users/lukas/jiminny/app
/Users/lukas/jiminny/app/app/Component/AiActivityType/Services...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Find in Files","depth":1,"bounds":{"left":0.2992021,"top":0.12609737,"width":0.024601065,"height":0.013567438},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"29 matches in 8 files","depth":1,"bounds":{"left":0.32779256,"top":0.12609737,"width":0.042220745,"height":0.013567438},"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"File mask:","depth":1,"bounds":{"left":0.5315825,"top":0.12290503,"width":0.029587766,"height":0.019952115},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXComboBox","text":"*.php","depth":1,"bounds":{"left":0.5621675,"top":0.11971269,"width":0.027925532,"height":0.027134877},"on_screen":true,"value":"*.php","role_description":"combo box","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"*.php","depth":6,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Auto","depth":6,"on_screen":false,"role_description":"text"},{"role":"AXTextField","text":"*.php","depth":2,"bounds":{"left":0.5661569,"top":0.12609737,"width":0.011635638,"height":0.013567438},"on_screen":true,"value":"*.php","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Filter Search Results","depth":1,"bounds":{"left":0.5944149,"top":0.12290503,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Pin Window","depth":1,"bounds":{"left":0.6037234,"top":0.12290503,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Search History","depth":1,"bounds":{"left":0.2962101,"top":0.15403032,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"$lockAcquired = Redis::set(self::POLLING_LOCK_KEY, json_encode($lockData), 'EX', self::LOCK_TTL_SECONDS, 'NX');","depth":2,"bounds":{"left":0.30718085,"top":0.15403032,"width":0.26196808,"height":0.017557861},"on_screen":true,"value":"$lockAcquired = Redis::set(self::POLLING_LOCK_KEY, json_encode($lockData), 'EX', self::LOCK_TTL_SECONDS, 'NX');","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":1,"bounds":{"left":0.578125,"top":0.15403032,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Match case","depth":1,"bounds":{"left":0.5880984,"top":0.15403032,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Words","depth":1,"bounds":{"left":0.59674203,"top":0.15403032,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Regex","depth":1,"bounds":{"left":0.60538566,"top":0.15403032,"width":0.00731383,"height":0.017557861},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Replace History","depth":1,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Replace","depth":2,"on_screen":false,"role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"New Line","depth":1,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Preserve case","depth":1,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In Project","depth":2,"bounds":{"left":0.2992021,"top":0.1867518,"width":0.022938829,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Module","depth":2,"bounds":{"left":0.32214096,"top":0.1867518,"width":0.019281914,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Directory","depth":2,"bounds":{"left":0.3414229,"top":0.1867518,"width":0.022606382,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Scope","depth":2,"bounds":{"left":0.36402926,"top":0.1867518,"width":0.017287234,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXPopUpButton","text":"Module","depth":1,"bounds":{"left":0.27027926,"top":1.0,"width":0.099734046,"height":0.0},"on_screen":false,"role_description":"pop up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXComboBox","text":"/Users/lukas/jiminny/app/app/Services/Crm/Hubspot","depth":1,"bounds":{"left":0.27027926,"top":1.0,"width":0.1974734,"height":0.0},"on_screen":false,"value":"/Users/lukas/jiminny/app/app/Services/Crm/Hubspot","role_description":"combo box","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"/Users/lukas/jiminny/app/app/Services/Crm/Hubspot","depth":6,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"/Users/lukas/jiminny/app/app/Console/Commands","depth":6,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"/Users/lukas/jiminny/app/tests/Unit/Services/Mail","depth":6,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"/Users/lukas/jiminny/app/app/Services/Mail","depth":6,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"/Users/lukas/jiminny/app/app/Console","depth":6,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"/Users/lukas/jiminny/app/storage/logs","depth":6,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"/Users/lukas/jiminny/app","depth":6,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"/Users/lukas/jiminny/app/app/Component/AiActivityType/Services","depth":6,"on_screen":false,"role_description":"text"}]...
|
-8513371325110625743
|
-5049823808272104445
|
visual_change
|
accessibility
|
NULL
|
Find in Files
29 matches in 8 files
File mask:
*.p Find in Files
29 matches in 8 files
File mask:
*.php
*.php
Auto
*.php
Filter Search Results
Pin Window
Search History
$lockAcquired = Redis::set(self::POLLING_LOCK_KEY, json_encode($lockData), 'EX', self::LOCK_TTL_SECONDS, 'NX');
New Line
Match case
Words
Regex
Replace History
Replace
New Line
Preserve case
In Project
Module
Directory
Scope
Module
/Users/lukas/jiminny/app/app/Services/Crm/Hubspot
/Users/lukas/jiminny/app/app/Services/Crm/Hubspot
/Users/lukas/jiminny/app/app/Console/Commands
/Users/lukas/jiminny/app/tests/Unit/Services/Mail
/Users/lukas/jiminny/app/app/Services/Mail
/Users/lukas/jiminny/app/app/Console
/Users/lukas/jiminny/app/storage/logs
/Users/lukas/jiminny/app
/Users/lukas/jiminny/app/app/Component/AiActivityType/Services...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85260
|
2921
|
9
|
2026-05-28T12:15:52.552186+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970552552_m2.jpg...
|
PhpStorm
|
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
SIUCKWindowHelpPwovscors#12121 on JY-20963-folProi SIUCKWindowHelpPwovscors#12121 on JY-20963-folProinet vecanyice pn.he bolbees.phe©ActivityControlier.php© VoiceConsentPrefix.phpNotificationsnObservers© AccountObserver.phpCyActwwooserver.pnp© ContactObserver.phgGroupObserver.pho© LeadObserver.phoC ProfileObserver.phpC SocialAccountObserver.phg© UserObserver.pho© UserRoleObserver.phc(in Policie:aProviders• Queuea Reoositonea RulesaServicesDa ActivityAiReodrleallendarConnerimermobiacte@ DecorateActivityDummym Helnarsv D Hubspor(i) AccountSyncStrategyMAetioneMcontndSuncstrateon• D DTO› FieldsThtauendOLeAkоkyscrco.onOneindi.onoMWiaKorCass wochexeR82* Breturn T The result of the APi callprivate function executeRequest(callable SapiCall)Opportunivsvncstratcov- Pac nation- Prosoec-SearchStrateo→- RedisService traits• Utils- Wechookc) Batchsunceo ector cho© BatchSvncRedisService.oCleantono@ GiosedDealStaapsSeniceScacheKey = Sthis->getRateLimitCacheKeyOScacheocxozresac = keozst.oet scachekeyif (is_string(ScachedExpiresAt) && is_numeric(ScachedExpiresAt)) 1Sremaining = naxl va(cint)) ScachedExpiresAt - tineon:hrow new kacetinzcexceoezonsrenaining,neruonSantwaittecarch leinronabieoi4 (Sthiso>isHubsootRateLinit(Se))thisosparse?erny.er e// NX: only the first job to receive a 429 in this burst sets the key./l Subsequent 429s in the same burst leave the TTL untouched so theIl window is not reset by every concurrent job hitting the linit.Redis::set(ScacheKey, (string) (tine() + SretryAfter).options:'EX', SretryAfter, "NX*);Sthis->log->warning( Hubspot) Received 429 from API'.iteanSdl'configid'= Sthis->config->getido.=) Sratmultten-ENAeMAONNATthrow new RateLinitException message: "Hubspot returned 429'. SretryAfter. Se):Throw Senclnaalise rccarica onoprivate function getRateLinitCachekevO: strinol...;=custom.loglaravel.logA console (STAGING)-782783704711[712713[PHONE]22.722723725727729E732-73.—73073- 738)TX: AUTONAND a.created_at › DATE_:GROUP BY u.id, u.email,ORDER BY sns_count DESCselect + Eron teans, wherlselect + Eron coles,SELECTCONCATU.Id, CASE WHsa.*t.ouner id FROM sociJOIN users u on u.id = sJOIN teans tWHERE u.tean_id = 1117 aSELECT * FROM actávitioSELECT * FROM actávitioSELECT * FROM crn configSELECT # FROM teans WHERselleetron usens whenseleetron miawhonkeselect + fron olavbookseleet ron eoeselect * fron crn_field.SELECT * FROM crn_field_AOTM con Brelds 4 0M 4• JOIN activities a ON $NHERF Actvity "d = 7002ANn & con nrovsden 3alSELECT * FROM activity.mselect * fron text relayselect * fron activitiesselect * fron users whenPARAtT GAAR MANGUREANOPAlRetGhAn dAAAIRdAMselect & fron teans wherPohattoon activtysHoeDMsActivityJiminnY ….# backend# buescontusion-dinig# donut_time#enpineerine# general# happy birthdavA infocoe intemal all# infra-chansed# infrastructure de#bu-team-infoiliminnv-bost olatform-team# platform-ticketstoroduct launche# random# release# suppor# thank-youssie the neoole of fimill6? Direct message.Vasil VasilenF8. Stefka Stoyanova1a llivana NetsevaAa Stovan TomovPetko Kashinski( Galva Dimitrova P: Todor Stamator1 Stelivan Georsie.D Vod&r MireNikolav Vanko&. James GrahamLukas Kovalky#:AppsS lin Gloudinu co moy to:loro@ Describe what you are looking forVasil Vasileve MessagerNoR0d canvis7 Files+Vasil Vasilev 2:56 PM1 с добър коментарDoory2e intentionaЗ сьщо e intentional поради факта, че phpredis dniver-a не поддьржа set ex +nх параметри, и тряова да се пуснат две операции set + expireLukas Kovalik 3.07 PMок. зз по пуснах пак поез gеminіlза третата точка обаче наистина ли няма подьржкааз май си ги ползвам някьлеVasil Vasilev 3:10 PMне става, бях го направил така, и се счупиLukas Kovalik 3:10 PMами и при мен се чумешеVasil Vasilev 3:11 PMpredis поддьржа set(Skey. Svalue. nx' - true, ex =60)Cnhnranic He caRaLukas Kovalik 3.14pNтака май не работеше Sresult = Redis=set(Stestkey, StestValue, "ax, Sttl, "NX*); а така да Sresult = Redis:set(StestKey, StestValue, [nx, 'ex' => Sttl)):Vasil Vasiley 2.11 pwLukas Kovalik 3.12 pNне помно BеUEVasil Vasilev 3:12 PMobоитноtо може nаeLukas Kovalik 3-12 PMможе и ла брькамVasil Vasilev 3:12 PMewons uusзначи пьрвото работиLukas Kovalik 313 PMmaueann/Somicac/crm/ithsnor/lciontnon..Vasil Vasiley 314 pvwe to ononnsMessage Vasil Vasiley...
|
NULL
|
1203767077918883082
|
NULL
|
click
|
ocr
|
NULL
|
SIUCKWindowHelpPwovscors#12121 on JY-20963-folProi SIUCKWindowHelpPwovscors#12121 on JY-20963-folProinet vecanyice pn.he bolbees.phe©ActivityControlier.php© VoiceConsentPrefix.phpNotificationsnObservers© AccountObserver.phpCyActwwooserver.pnp© ContactObserver.phgGroupObserver.pho© LeadObserver.phoC ProfileObserver.phpC SocialAccountObserver.phg© UserObserver.pho© UserRoleObserver.phc(in Policie:aProviders• Queuea Reoositonea RulesaServicesDa ActivityAiReodrleallendarConnerimermobiacte@ DecorateActivityDummym Helnarsv D Hubspor(i) AccountSyncStrategyMAetioneMcontndSuncstrateon• D DTO› FieldsThtauendOLeAkоkyscrco.onOneindi.onoMWiaKorCass wochexeR82* Breturn T The result of the APi callprivate function executeRequest(callable SapiCall)Opportunivsvncstratcov- Pac nation- Prosoec-SearchStrateo→- RedisService traits• Utils- Wechookc) Batchsunceo ector cho© BatchSvncRedisService.oCleantono@ GiosedDealStaapsSeniceScacheKey = Sthis->getRateLimitCacheKeyOScacheocxozresac = keozst.oet scachekeyif (is_string(ScachedExpiresAt) && is_numeric(ScachedExpiresAt)) 1Sremaining = naxl va(cint)) ScachedExpiresAt - tineon:hrow new kacetinzcexceoezonsrenaining,neruonSantwaittecarch leinronabieoi4 (Sthiso>isHubsootRateLinit(Se))thisosparse?erny.er e// NX: only the first job to receive a 429 in this burst sets the key./l Subsequent 429s in the same burst leave the TTL untouched so theIl window is not reset by every concurrent job hitting the linit.Redis::set(ScacheKey, (string) (tine() + SretryAfter).options:'EX', SretryAfter, "NX*);Sthis->log->warning( Hubspot) Received 429 from API'.iteanSdl'configid'= Sthis->config->getido.=) Sratmultten-ENAeMAONNATthrow new RateLinitException message: "Hubspot returned 429'. SretryAfter. Se):Throw Senclnaalise rccarica onoprivate function getRateLinitCachekevO: strinol...;=custom.loglaravel.logA console (STAGING)-782783704711[712713[PHONE]22.722723725727729E732-73.—73073- 738)TX: AUTONAND a.created_at › DATE_:GROUP BY u.id, u.email,ORDER BY sns_count DESCselect + Eron teans, wherlselect + Eron coles,SELECTCONCATU.Id, CASE WHsa.*t.ouner id FROM sociJOIN users u on u.id = sJOIN teans tWHERE u.tean_id = 1117 aSELECT * FROM actávitioSELECT * FROM actávitioSELECT * FROM crn configSELECT # FROM teans WHERselleetron usens whenseleetron miawhonkeselect + fron olavbookseleet ron eoeselect * fron crn_field.SELECT * FROM crn_field_AOTM con Brelds 4 0M 4• JOIN activities a ON $NHERF Actvity "d = 7002ANn & con nrovsden 3alSELECT * FROM activity.mselect * fron text relayselect * fron activitiesselect * fron users whenPARAtT GAAR MANGUREANOPAlRetGhAn dAAAIRdAMselect & fron teans wherPohattoon activtysHoeDMsActivityJiminnY ….# backend# buescontusion-dinig# donut_time#enpineerine# general# happy birthdavA infocoe intemal all# infra-chansed# infrastructure de#bu-team-infoiliminnv-bost olatform-team# platform-ticketstoroduct launche# random# release# suppor# thank-youssie the neoole of fimill6? Direct message.Vasil VasilenF8. Stefka Stoyanova1a llivana NetsevaAa Stovan TomovPetko Kashinski( Galva Dimitrova P: Todor Stamator1 Stelivan Georsie.D Vod&r MireNikolav Vanko&. James GrahamLukas Kovalky#:AppsS lin Gloudinu co moy to:loro@ Describe what you are looking forVasil Vasileve MessagerNoR0d canvis7 Files+Vasil Vasilev 2:56 PM1 с добър коментарDoory2e intentionaЗ сьщо e intentional поради факта, че phpredis dniver-a не поддьржа set ex +nх параметри, и тряова да се пуснат две операции set + expireLukas Kovalik 3.07 PMок. зз по пуснах пак поез gеminіlза третата точка обаче наистина ли няма подьржкааз май си ги ползвам някьлеVasil Vasilev 3:10 PMне става, бях го направил така, и се счупиLukas Kovalik 3:10 PMами и при мен се чумешеVasil Vasilev 3:11 PMpredis поддьржа set(Skey. Svalue. nx' - true, ex =60)Cnhnranic He caRaLukas Kovalik 3.14pNтака май не работеше Sresult = Redis=set(Stestkey, StestValue, "ax, Sttl, "NX*); а така да Sresult = Redis:set(StestKey, StestValue, [nx, 'ex' => Sttl)):Vasil Vasiley 2.11 pwLukas Kovalik 3.12 pNне помно BеUEVasil Vasilev 3:12 PMobоитноtо може nаeLukas Kovalik 3-12 PMможе и ла брькамVasil Vasilev 3:12 PMewons uusзначи пьрвото работиLukas Kovalik 313 PMmaueann/Somicac/crm/ithsnor/lciontnon..Vasil Vasiley 314 pvwe to ononnsMessage Vasil Vasiley...
|
85257
|
NULL
|
NULL
|
NULL
|
|
85259
|
2920
|
9
|
2026-05-28T12:15:51.913854+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970551913_m1.jpg...
|
iTerm2
|
NULL
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
PhpStormFileEditViewNavigateCodeRefactorRunToolsGi PhpStormFileEditViewNavigateCodeRefactorRunToolsGitWindowHelpec2-user@ip-10-30-129-190:~screenpipe"O ₴4‹$0(ah]100% <78• Thu 28 May 15:15:51181ec2-user@ip-10-30-140-…₴7DOCKER#_####_#####\\###||\#/V~'881DEV (-zsh)O [EMAIL] Linux 2023 (ECS Optimized)_/m/For documentation, visit [URL_WITH_CREDENTIALS] ~]$ exitlogoutConnection to jiminny-prod-ecsi closed.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ applukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ vprodWarning: Permanently added 'jiminny-prod-ecs1' (ED25519) to the list of known hosts.A newer release of "Amazon Linux" is available.Version 2023.10.20260330:Version 2023.11.20260406:Version 2023.11.20260413:Version2023.11.20260427:Version2023.11.20260505:Version 2023.11.20260509:Version 2023.11.20260511:Version 2023.11.20260514:Run "/usr/bin/dnf check-release-update" for full release and version update info#_~\ ####_\ #####\\###1\#/Amazon Linux 2023 (ECS Optimized)/m/'For documentation, visit [URL_WITH_CREDENTIALS] ~]$ client_loop: send disconnect: Broken pipeukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-relay) $I...
|
NULL
|
-8167783595720104576
|
NULL
|
click
|
ocr
|
NULL
|
PhpStormFileEditViewNavigateCodeRefactorRunToolsGi PhpStormFileEditViewNavigateCodeRefactorRunToolsGitWindowHelpec2-user@ip-10-30-129-190:~screenpipe"O ₴4‹$0(ah]100% <78• Thu 28 May 15:15:51181ec2-user@ip-10-30-140-…₴7DOCKER#_####_#####\\###||\#/V~'881DEV (-zsh)O [EMAIL] Linux 2023 (ECS Optimized)_/m/For documentation, visit [URL_WITH_CREDENTIALS] ~]$ exitlogoutConnection to jiminny-prod-ecsi closed.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ applukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ vprodWarning: Permanently added 'jiminny-prod-ecs1' (ED25519) to the list of known hosts.A newer release of "Amazon Linux" is available.Version 2023.10.20260330:Version 2023.11.20260406:Version 2023.11.20260413:Version2023.11.20260427:Version2023.11.20260505:Version 2023.11.20260509:Version 2023.11.20260511:Version 2023.11.20260514:Run "/usr/bin/dnf check-release-update" for full release and version update info#_~\ ####_\ #####\\###1\#/Amazon Linux 2023 (ECS Optimized)/m/'For documentation, visit [URL_WITH_CREDENTIALS] ~]$ client_loop: send disconnect: Broken pipeukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-relay) $I...
|
85258
|
NULL
|
NULL
|
NULL
|
|
85258
|
2920
|
8
|
2026-05-28T12:15:49.334225+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970549334_m1.jpg...
|
Slack
|
Vasil Vasilev (DM) - Jiminny Inc - 3 new items - S Vasil Vasilev (DM) - Jiminny Inc - 3 new items - Slack...
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки
Today at 1:25:47 PM
1:25
процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип
Today at 1:26:15 PM
1:26
и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity
Lukas Kovalik
Today at 2:45:12 PM
2:45 PM
Не знам това дали е релевантно
Today at 2:45:14 PM
2:45
1.
Shared Elasticsearch Sockets:
Because
pcntl_fork()
clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in
resetAfterFork()
(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and
cURL
exceptions.
2.
Supervisor Shutdown Deadlock:
In
reapChildren()
, calling
pcntl_waitpid()
without the
WNOHANG
flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.
(edited)
Today at 2:45:29 PM
2:45
3.
Non-Atomic Redis Locks:
The new
ReindexTargetStatsReporter
checks the lock with
get
and then creates it with
set
. Because the workers are truly parallel, they can both read
null
at the exact same microsecond and both push duplicate metrics to Datadog. This needs to be a single, atomic command (e.g.,
set
with
NX
).
Vasil Vasilev
Today at 2:56:52 PM
2:56 PM
1 e добър коментар,
React with white_check_mark
React with eyes
React with raised_hands...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Later","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Later","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"More…","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"More","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Unreads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Threads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Huddles","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Drafts & sent","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Directories","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-backend-engineers","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-inner-team","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ai-chapter","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"alerts","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"backend","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"bugs","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"confusion-clinic","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"donut_time","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"engineering","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"general","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"happy_birthday","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infosec_internal_all","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infra-changes","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infrastructure_dev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"jbu-team-info","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"jiminny-bg","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"platform-team","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"platform-tickets","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"product_launches","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"random","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"releases","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"support","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"thank-yous","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"the_people_of_jiminny","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Vasil Vasilev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Stefka Stoyanova","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Iliyana Netseva","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Stoyan Tomov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Petko Kashinski","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Galya Dimitrova","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Todor Stamatov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Steliyan Georgiev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Ves","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Mira","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Nikolay Yankov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"James Graham","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Lukas Kovalik","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"you","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Jira Cloud","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Toast","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Google Calendar","depth":15,"bounds":{"left":0.56805557,"top":0.0,"width":0.06388889,"height":0.02},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.56805557,"top":0.0,"width":0.007638889,"height":0.02}},{"char_start":1,"char_count":14,"bounds":{"left":0.57569444,"top":0.0,"width":0.06875,"height":0.02}}],"role_description":"text"},{"role":"AXRadioButton","text":"Messages","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Messages","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Add canvas","depth":10,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Add canvas","depth":12,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Pins","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Pins","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Add and Edit Channel Tabs","depth":9,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Canvas","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"List","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Folder","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Jump to date","depth":14,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Today at 12:00:37 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"малко по късно и на мен ще ми трябва ревю за един голям feature","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:46 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"но ще ти пиша, като е готов за гледане","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(edited)","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:11:37 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:11 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ок , mersi","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:23:53 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:23 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"като имаш време, разгледай този интересен ПР:","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"https://github.com/jiminny/app/pull/12130","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"https://github.com/jiminny/app/pull/12130","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:25:05 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:25","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:25:47 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:25","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:26:15 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:26","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:12 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Не знам това дали е релевантно","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:14 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1.","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Shared Elasticsearch Sockets:","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Because","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"pcntl_fork()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"resetAfterFork()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"cURL","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"exceptions.","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"2.","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Supervisor Shutdown Deadlock:","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"In","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"reapChildren()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":", calling","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"pcntl_waitpid()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"without the","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"WNOHANG","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(edited)","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:29 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"3.","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Non-Atomic Redis Locks:","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"The new","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ReindexTargetStatsReporter","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"checks the lock with","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"get","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"and then creates it with","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"set","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":". Because the workers are truly parallel, they can both read","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"null","depth":17,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"at the exact same microsecond and both push duplicate metrics to Datadog. This needs to be a single, atomic command (e.g.,","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"set","depth":17,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"with","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"NX","depth":17,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":").","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXLink","text":"Today at 2:56:52 PM","depth":15,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:56 PM","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1 e добър коментар,","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"React with white_check_mark","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with eyes","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with raised_hands","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
328364737081514531
|
-2155069979724893602
|
click
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки
Today at 1:25:47 PM
1:25
процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип
Today at 1:26:15 PM
1:26
и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity
Lukas Kovalik
Today at 2:45:12 PM
2:45 PM
Не знам това дали е релевантно
Today at 2:45:14 PM
2:45
1.
Shared Elasticsearch Sockets:
Because
pcntl_fork()
clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in
resetAfterFork()
(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and
cURL
exceptions.
2.
Supervisor Shutdown Deadlock:
In
reapChildren()
, calling
pcntl_waitpid()
without the
WNOHANG
flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.
(edited)
Today at 2:45:29 PM
2:45
3.
Non-Atomic Redis Locks:
The new
ReindexTargetStatsReporter
checks the lock with
get
and then creates it with
set
. Because the workers are truly parallel, they can both read
null
at the exact same microsecond and both push duplicate metrics to Datadog. This needs to be a single, atomic command (e.g.,
set
with
NX
).
Vasil Vasilev
Today at 2:56:52 PM
2:56 PM
1 e добър коментар,
React with white_check_mark
React with eyes
React with raised_hands
PhpStormFileEditViewNavigateCodeRefactorRunToolsGitWindowHelpec2-user@ip-10-30-129-190:~screenpipe"O ₴4‹$0(ah]100% <78• Thu 28 May 15:15:48181ec2-user@ip-10-30-140-...₴7DOCKER#_####_#####\\###||\#/V~'881DEV (-zsh)O [EMAIL] Linux 2023 (ECS Optimized)_/m/For documentation, visit [URL_WITH_CREDENTIALS] ~]$ exitlogoutConnection to jiminny-prod-ecsi closed.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ applukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ vprodWarning: Permanently added 'jiminny-prod-ecs1' (ED25519) to the list of known hosts.A newer release of "Amazon Linux" is available.Version 2023.10.20260330:Version 2023.11.20260406:Version 2023.11.20260413:Version2023.11.20260427:Version2023.11.20260505:Version 2023.11.20260509:Version 2023.11.20260511:Version 2023.11.20260514:Run "/usr/bin/dnf check-release-update" for full release and version update info#_~\ ####_\ #####\\###1\#/Amazon Linux 2023 (ECS Optimized)/m/'For documentation, visit [URL_WITH_CREDENTIALS] ~]$ client_loop: send disconnect: Broken pipeukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-relay) $I...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85257
|
2921
|
8
|
2026-05-28T12:15:49.232729+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970549232_m2.jpg...
|
Slack
|
Vasil Vasilev (DM) - Jiminny Inc - 3 new items - S Vasil Vasilev (DM) - Jiminny Inc - 3 new items - Slack...
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"bounds":{"left":0.5056516,"top":0.058260176,"width":0.011968086,"height":0.028731046},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"bounds":{"left":0.50299203,"top":0.10055866,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"bounds":{"left":0.50664896,"top":0.13806863,"width":0.009973404,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"bounds":{"left":0.50299203,"top":0.15482841,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":8,"bounds":{"left":0.50764626,"top":0.19233839,"width":0.007978723,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":6,"bounds":{"left":0.50299203,"top":0.20909816,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":8,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.012965426,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.0026595744,"height":0.011173184}},{"char_start":1,"char_count":7,"bounds":{"left":0.50764626,"top":0.24660814,"width":0.010638298,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":6,"bounds":{"left":0.50299203,"top":0.26336792,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":8,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0076462766,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5099734,"top":0.3008779,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Later","depth":6,"bounds":{"left":0.50299203,"top":0.31763768,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Later","depth":8,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.008643617,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5093085,"top":0.35514766,"width":0.0066489363,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"More…","depth":6,"bounds":{"left":0.50299203,"top":0.3719074,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"More","depth":8,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.008976064,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.0033244682,"height":0.011173184}},{"char_start":1,"char_count":3,"bounds":{"left":0.5106383,"top":0.4094174,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXStaticText","text":"Unreads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Threads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Huddles","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Drafts & sent","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Directories","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-backend-engineers","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-inner-team","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ai-chapter","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"alerts","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"backend","depth":15,"bounds":{"left":0.5422208,"top":0.09736632,"width":0.018284574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.09736632,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54521275,"top":0.09736632,"width":0.015292553,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"bugs","depth":15,"bounds":{"left":0.5422208,"top":0.11971269,"width":0.010638298,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.11971269,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":3,"bounds":{"left":0.54521275,"top":0.11971269,"width":0.00731383,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"confusion-clinic","depth":15,"bounds":{"left":0.5422208,"top":0.14205906,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.14205906,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54454786,"top":0.14205906,"width":0.032247342,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"donut_time","depth":15,"bounds":{"left":0.5422208,"top":0.16440542,"width":0.025265958,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.16440542,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54521275,"top":0.16440542,"width":0.022273935,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"engineering","depth":15,"bounds":{"left":0.5422208,"top":0.1867518,"width":0.025930852,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.1867518,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":10,"bounds":{"left":0.54488033,"top":0.1867518,"width":0.022938829,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"general","depth":15,"bounds":{"left":0.5422208,"top":0.20909816,"width":0.016289894,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.20909816,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54488033,"top":0.20909816,"width":0.013297873,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"happy_birthday","depth":15,"bounds":{"left":0.5422208,"top":0.23144454,"width":0.033909574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.23144454,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.54521275,"top":0.23144454,"width":0.030917553,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infosec_internal_all","depth":15,"bounds":{"left":0.5422208,"top":0.25379092,"width":0.041888297,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.25379092,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":19,"bounds":{"left":0.54355055,"top":0.25379092,"width":0.040226065,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infra-changes","depth":15,"bounds":{"left":0.5422208,"top":0.27613726,"width":0.029587766,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.27613726,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54355055,"top":0.27613726,"width":0.02825798,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infrastructure_dev","depth":15,"bounds":{"left":0.5422208,"top":0.29848364,"width":0.040226065,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.29848364,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":17,"bounds":{"left":0.54355055,"top":0.29848364,"width":0.038896278,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"jbu-team-info","depth":15,"bounds":{"left":0.5422208,"top":0.32083002,"width":0.029920213,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.32083002,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54355055,"top":0.32083002,"width":0.028590426,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"jiminny-bg","depth":15,"bounds":{"left":0.5422208,"top":0.34317636,"width":0.023271276,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.34317636,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54355055,"top":0.34317636,"width":0.021609042,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"platform-team","depth":15,"bounds":{"left":0.5422208,"top":0.36552274,"width":0.03158245,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.36552274,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54521275,"top":0.36552274,"width":0.028590426,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"platform-tickets","depth":15,"bounds":{"left":0.5422208,"top":0.38786912,"width":0.034906916,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.38786912,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54521275,"top":0.38786912,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"product_launches","depth":15,"bounds":{"left":0.5422208,"top":0.4102155,"width":0.03856383,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.4102155,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54521275,"top":0.4102155,"width":0.03557181,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"random","depth":15,"bounds":{"left":0.5422208,"top":0.43256184,"width":0.016954787,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.43256184,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":5,"bounds":{"left":0.54421544,"top":0.43256184,"width":0.014960106,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"releases","depth":15,"bounds":{"left":0.5422208,"top":0.45490822,"width":0.018284574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.45490822,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":7,"bounds":{"left":0.54421544,"top":0.45490822,"width":0.016289894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"support","depth":15,"bounds":{"left":0.5422208,"top":0.4772546,"width":0.017287234,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.4772546,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54454786,"top":0.4772546,"width":0.01462766,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"thank-yous","depth":15,"bounds":{"left":0.5422208,"top":0.49960095,"width":0.024601065,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.49960095,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54421544,"top":0.49960095,"width":0.022606382,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"the_people_of_jiminny","depth":15,"bounds":{"left":0.5422208,"top":0.5219473,"width":0.045212764,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5219473,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":20,"bounds":{"left":0.54421544,"top":0.5219473,"width":0.04720745,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Vasil Vasilev","depth":15,"bounds":{"left":0.5422208,"top":0.5746209,"width":0.026595745,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5746209,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54521275,"top":0.5746209,"width":0.023271276,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Stefka Stoyanova","depth":15,"bounds":{"left":0.5422208,"top":0.5969673,"width":0.037898935,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5969673,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54488033,"top":0.5969673,"width":0.03523936,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Iliyana Netseva","depth":15,"bounds":{"left":0.5422208,"top":0.61931366,"width":0.03324468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.61931366,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54355055,"top":0.61931366,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Stoyan Tomov","depth":15,"bounds":{"left":0.5422208,"top":0.64166003,"width":0.030917553,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.64166003,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":11,"bounds":{"left":0.54488033,"top":0.64166003,"width":0.027925532,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Petko Kashinski","depth":15,"bounds":{"left":0.5422208,"top":0.6640064,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.6640064,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54521275,"top":0.6640064,"width":0.03158245,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Galya Dimitrova","depth":15,"bounds":{"left":0.5422208,"top":0.6863527,"width":0.03523936,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.6863527,"width":0.003656915,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54587764,"top":0.6863527,"width":0.03158245,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Todor Stamatov","depth":15,"bounds":{"left":0.5422208,"top":0.7086991,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7086991,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.54454786,"top":0.7086991,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Steliyan Georgiev","depth":15,"bounds":{"left":0.5422208,"top":0.7310455,"width":0.038231384,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7310455,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":16,"bounds":{"left":0.54488033,"top":0.7310455,"width":0.03557181,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Ves","depth":15,"bounds":{"left":0.5422208,"top":0.75339186,"width":0.007978723,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.75339186,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":2,"bounds":{"left":0.54521275,"top":0.75339186,"width":0.004986702,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Mira","depth":15,"bounds":{"left":0.5422208,"top":0.77573824,"width":0.010305851,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.77573824,"width":0.004654255,"height":0.014365523}},{"char_start":1,"char_count":3,"bounds":{"left":0.546875,"top":0.77573824,"width":0.005319149,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Nikolay Yankov","depth":15,"bounds":{"left":0.5422208,"top":0.7980846,"width":0.032912236,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7980846,"width":0.0039893617,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.5462101,"top":0.7980846,"width":0.028922873,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"James Graham","depth":15,"bounds":{"left":0.5422208,"top":0.820431,"width":0.031914894,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.820431,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":11,"bounds":{"left":0.54421544,"top":0.820431,"width":0.029920213,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Lukas Kovalik","depth":15,"bounds":{"left":0.5422208,"top":0.8427773,"width":0.029587766,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.8427773,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54488033,"top":0.8427773,"width":0.026928192,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"you","depth":15,"bounds":{"left":0.5744681,"top":0.8427773,"width":0.0063164895,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5744681,"top":0.8427773,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":2,"bounds":{"left":0.5767952,"top":0.8427773,"width":0.0056515955,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Jira Cloud","depth":15,"bounds":{"left":0.5422208,"top":0.8954509,"width":0.021941489,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.8954509,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54421544,"top":0.8954509,"width":0.019946808,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Toast","depth":15,"bounds":{"left":0.5422208,"top":0.91779727,"width":0.011635638,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.91779727,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":4,"bounds":{"left":0.54454786,"top":0.91779727,"width":0.00930851,"height":0.014365523}}],"role_description":"text"}]...
|
-1344434917273675558
|
-5802376096808494354
|
click
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
SIUCKWindowHelpPwovscors#12121 on JY-20963-folProinet vecanyice pn.he bolbees.phe©ActivityControlier.php© VoiceConsentPrefix.phpNotificationsnObservers© AccountObserver.phpCyActwwooserver.pnp© ContactObserver.phpGroupObserver.pho© LeadObserver.phoC ProfileObserver.phpC SocialAccountObserver.phg© UserObserver.pho© UserRoleObserver.phc(in Policie:aProviders• Queuea Reoositonea RulesaServicesDa ActivityAiReodrleallendarConnerimermobiacte@ DecorateActivityDummym Helnarsv D Hubspor(i) AccountSyncStrategyMAetioneMcontctSwnestrateon• D DTO› FieldsThtauendOLekоkyseiwico.onOAeindi.oneMWiaKorCass wochexeOpportunivsvncstratcov- Pac nation- Prosoec-SearchStrateo→- RedisService traits• Utils- Wechookc) Batchsunceo ector cho© BatchSvncRedisService.oCleantono@ GiosedDealStaapsSeniceclnaalise rccarica ono* Breturn T The result of the APi callprivate function executeRequest(callable SapiCall)ScacheKey = Sthis->getRateLimitCacheKeyOScacheocxozresac = keozst.oet scachekeyif (is_string(ScachedExpiresAt) && is_numeric(ScachedExpiresAt)) 1Sremaining = naxl va(cint)) ScachedExpiresAt - tineon:hrow new kacetinzcexceoezonsrenaining,neruonSantwaittecarch leinronabieoi4 (Sthiso>isHubsootRateLinit(Se))thisosparse?erny.er e// NX: only the first job to receive a 429 in this burst sets the key.// Subsequent 42%s in the same burst leave the TTL untouched so theIl window is not reset by every concurrent job hitting the linit.Redis::set(ScacheKey, (string) (tine() + SretryAfter).options:'EX', SretryAfter, "NX*);Sthis->log->warning( Hubspot) Received 429 from API'. (iteanSdl'configid'= Sthis->config->getido.=) Sratmultten-ENAeMAONNATthrow new RateLinitException message: "Hubspot returned 429'. SretryAfter. Se):Throw Senprivate function getRateLinitCachekevO: strinol...;=custom.loglaravel.logA console [STAGING—78278578785786711[712713[PHONE]725727728729E732-733—730737- 738)TX: AUTONAND a.created_at › DATE_:GROUP BY u.id, u.email,ORDER BY sne count DESMselect + Eron teans, wherlselect + Eron coles,SELECTCONCATU.Id, CASE WHsa.*t.ouner id FROM sociJOIN users u on u.id = sJOIN teans tWHERE u.tean_id = 1117 aSELECT * FROM actávitioSELECT * FROM actávitioSELECT * FROM crn configSELECT # FROM teans WHERselleetron usens whenselect * fron playbooksseleetron miawhonkeselect * fron playbook_ctseleet ron eoeselect * fron crn_field.vSELECT * FROM crn_field_AOTM con Brelds 4 0M 4• JOIN activities a ON $NHERF Actvity "d = 7002AND € con onovider saSELECT * FROM activity.mselect * fron text relayselect * fron activitiesselect * fron users whenPARAtT GAAR MANGUREANOPAlRetGhAn dAAAIRdAMPolhnttene neard wharselect * fron teans wherPohattoon activtysHoeDMsActivityJiminnY ….# backend# buescontusion-dinig# donut_time#enpineerine# generall# happy birthdavA infocoe intemal all# infra-chansed# infrastructure de#bu-team-infoiliminny-be# platform-team# platform-ticketstoroduct launche# random# release# suppor# thank-youssie the neoole of fimill6? Direct message.Vasil VasilenF8. Stefka Stoyanova1a llivana NetsevaA Ctovan TomnulPetko KashinskiGola Nimitrous: Todor Stamatol1 Stelivan Georsie.&r MireNikolav Vanko&. James GrahamLukas KovalkyInu cowoy 10:10.e@ Describe what you are looking forVasil Vasileve MessagerNoR0d canvisfiles.Vasil Vasilev 2:56 PM1 с добър коментарDoory2e intentionaЗ сьщо e intentional поради факта, че phpredis dniver-a не поддьржа set ex +nх параметри, и тряова да се пуснат две операции set + expireLukas Kovalik 3.07 PMок. зз по пуснах пак поез gеminіlза третата точка обаче наистина ли няма подьржкааз май си ги ползвам някьлеVasil Vasilev 3:10 PMне става, бях го направил така, и се счупиLukas Kovalik 3:10 PMами и при мен се чумешеVasil Vasilev 3:11 PMpredis поддьржа set(Skey. Svalue. nx' - true, ex =60)Cnhnranic He caRaLukas Kovalik 3.14pNтака май не работеше Sresult = Redis=set(Stestkey, StestValue, "ax, Sttl, "NX*); а така да Sresult = Redis:set(StestKey, StestValue, [nx, 'ex' => Sttl)):Vasil Vasiley 2.11 pwLukas Kovalik 3.12 pNне помно BеUEVasil Vasilev 3:12 PMobоитноtо може nаeLukas Kovalik 3-12 PMможе и ла брькамVacil Vaciley 242 pwewons uusSlockAcquired - Redis::set(self::POLLING LOCK KEY, ison encode(SlockData). "EX', self::LOCK TTL SECONDS. *NX*)значи пьрвото работиLukas Kovalik 313 PMwe to ononns...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85256
|
2920
|
7
|
2026-05-28T12:15:30.347263+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970530347_m1.jpg...
|
Slack
|
Vasil Vasilev (DM) - Jiminny Inc - 3 new items - S Vasil Vasilev (DM) - Jiminny Inc - 3 new items - Slack...
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки
Today at 1:25:47 PM
1:25
процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип
Today at 1:26:15 PM
1:26
и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity
Lukas Kovalik
Today at 2:45:12 PM
2:45 PM
Не знам това дали е релевантно
Today at 2:45:14 PM
2:45
1.
Shared Elasticsearch Sockets:
Because
pcntl_fork()
clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in
resetAfterFork()
(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and
cURL
exceptions.
2.
Supervisor Shutdown Deadlock:
In
reapChildren()
, calling
pcntl_waitpid()
without the
WNOHANG
flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.
(edited)
Today at 2:45:29 PM
2:45
3.
Non-Atomic Redis Locks:
The new
ReindexTargetStatsReporter
checks the lock with
get
and then creates it with
set
. Because the workers are truly parallel, they can both read
null
at the exact same microsecond and both push duplicate metrics to Datadog. This needs to be a single, atomic command (e.g.,
set
with
NX
).
Vasil Vasilev
Today at 2:56:52 PM
2:56 PM
1 e добър коментар,...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Later","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Later","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"More…","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"More","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Unreads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Threads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Huddles","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Drafts & sent","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Directories","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-backend-engineers","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-inner-team","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ai-chapter","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"alerts","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"backend","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"bugs","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"confusion-clinic","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"donut_time","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"engineering","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"general","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"happy_birthday","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infosec_internal_all","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infra-changes","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infrastructure_dev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"jbu-team-info","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"jiminny-bg","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"platform-team","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"platform-tickets","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"product_launches","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"random","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"releases","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"support","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"thank-yous","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"the_people_of_jiminny","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Vasil Vasilev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Stefka Stoyanova","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Iliyana Netseva","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Stoyan Tomov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Petko Kashinski","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Galya Dimitrova","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Todor Stamatov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Steliyan Georgiev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Ves","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Mira","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Nikolay Yankov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"James Graham","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Lukas Kovalik","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"you","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Jira Cloud","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Toast","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Google Calendar","depth":15,"bounds":{"left":0.56805557,"top":0.0,"width":0.06388889,"height":0.02},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.56805557,"top":0.0,"width":0.007638889,"height":0.02}},{"char_start":1,"char_count":14,"bounds":{"left":0.57569444,"top":0.0,"width":0.06875,"height":0.02}}],"role_description":"text"},{"role":"AXRadioButton","text":"Messages","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Messages","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Add canvas","depth":10,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Add canvas","depth":12,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Pins","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Pins","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Add and Edit Channel Tabs","depth":9,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Canvas","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"List","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Folder","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Jump to date","depth":14,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Today at 12:00:37 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"малко по късно и на мен ще ми трябва ревю за един голям feature","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:46 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"но ще ти пиша, като е готов за гледане","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(edited)","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:11:37 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:11 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ок , mersi","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:23:53 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:23 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"като имаш време, разгледай този интересен ПР:","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"https://github.com/jiminny/app/pull/12130","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"https://github.com/jiminny/app/pull/12130","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:25:05 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:25","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:25:47 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:25","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:26:15 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:26","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:12 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Не знам това дали е релевантно","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:14 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1.","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Shared Elasticsearch Sockets:","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Because","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"pcntl_fork()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"resetAfterFork()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"cURL","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"exceptions.","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"2.","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Supervisor Shutdown Deadlock:","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"In","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"reapChildren()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":", calling","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"pcntl_waitpid()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"without the","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"WNOHANG","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(edited)","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:29 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"3.","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Non-Atomic Redis Locks:","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"The new","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ReindexTargetStatsReporter","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"checks the lock with","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"get","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"and then creates it with","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"set","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":". Because the workers are truly parallel, they can both read","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"null","depth":17,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"at the exact same microsecond and both push duplicate metrics to Datadog. This needs to be a single, atomic command (e.g.,","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"set","depth":17,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"with","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"NX","depth":17,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":").","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXLink","text":"Today at 2:56:52 PM","depth":15,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:56 PM","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1 e добър коментар,","depth":16,"on_screen":true,"role_description":"text"}]...
|
-5247781899694968478
|
-2155074377771404706
|
idle
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки
Today at 1:25:47 PM
1:25
процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип
Today at 1:26:15 PM
1:26
и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity
Lukas Kovalik
Today at 2:45:12 PM
2:45 PM
Не знам това дали е релевантно
Today at 2:45:14 PM
2:45
1.
Shared Elasticsearch Sockets:
Because
pcntl_fork()
clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in
resetAfterFork()
(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and
cURL
exceptions.
2.
Supervisor Shutdown Deadlock:
In
reapChildren()
, calling
pcntl_waitpid()
without the
WNOHANG
flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.
(edited)
Today at 2:45:29 PM
2:45
3.
Non-Atomic Redis Locks:
The new
ReindexTargetStatsReporter
checks the lock with
get
and then creates it with
set
. Because the workers are truly parallel, they can both read
null
at the exact same microsecond and both push duplicate metrics to Datadog. This needs to be a single, atomic command (e.g.,
set
with
NX
).
Vasil Vasilev
Today at 2:56:52 PM
2:56 PM
1 e добър коментар,
PhpStormFileEditViewNavigateCodeRefactorRunToolsGitWindowHelpec2-user@ip-10-30-129-190:~screenpipe"84‹$0(ah]100% <78• Thu 28 May 15:15:30181ec2-user@ip-10-30-140-...₴7DOCKER#_####_#####\\###||\#/V~'881DEV (-zsh)O [EMAIL] Linux 2023 (ECS Optimized)_/m/For documentation, visit [URL_WITH_CREDENTIALS] ~]$ exitlogoutConnection to jiminny-prod-ecsi closed.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ applukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ vprodWarning: Permanently added 'jiminny-prod-ecs1' (ED25519) to the list of known hosts.A newer release of "Amazon Linux" is available.Version 2023.10.20260330:Version 2023.11.20260406:Version 2023.11.20260413:Version2023.11.20260427:Version2023.11.20260505:Version 2023.11.20260509:Version 2023.11.20260511:Version 2023.11.20260514:Run "/usr/bin/dnf check-release-update" for full release and version update info#_~\ ####_\ #####\\###1\#/Amazon Linux 2023 (ECS Optimized)/m/'For documentation, visit [URL_WITH_CREDENTIALS] ~]$ client_loop: send disconnect: Broken pipeukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-relay) $I...
|
85254
|
NULL
|
NULL
|
NULL
|
|
85255
|
2921
|
7
|
2026-05-28T12:15:29.070165+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970529070_m2.jpg...
|
Slack
|
Vasil Vasilev (DM) - Jiminny Inc - 3 new items - S Vasil Vasilev (DM) - Jiminny Inc - 3 new items - Slack...
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки
Today at 1:25:47 PM
1:25
процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип
Today at 1:26:15 PM
1:26
и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity
Lukas Kovalik
Today at 2:45:12 PM
2:45 PM
Не знам това дали е релевантно
Today at 2:45:14 PM
2:45
1.
Shared Elasticsearch Sockets:
Because
pcntl_fork()
clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in
resetAfterFork()
(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and
cURL
exceptions.
2.
Supervisor Shutdown Deadlock:
In
reapChildren()
, calling
pcntl_waitpid()
without the
WNOHANG
flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.
(edited)
Today at 2:45:29 PM...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"bounds":{"left":0.5056516,"top":0.058260176,"width":0.011968086,"height":0.028731046},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"bounds":{"left":0.50299203,"top":0.10055866,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"bounds":{"left":0.50664896,"top":0.13806863,"width":0.009973404,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"bounds":{"left":0.50299203,"top":0.15482841,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":8,"bounds":{"left":0.50764626,"top":0.19233839,"width":0.007978723,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":6,"bounds":{"left":0.50299203,"top":0.20909816,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":8,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.012965426,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.0026595744,"height":0.011173184}},{"char_start":1,"char_count":7,"bounds":{"left":0.50764626,"top":0.24660814,"width":0.010638298,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":6,"bounds":{"left":0.50299203,"top":0.26336792,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":8,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0076462766,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5099734,"top":0.3008779,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Later","depth":6,"bounds":{"left":0.50299203,"top":0.31763768,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Later","depth":8,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.008643617,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5093085,"top":0.35514766,"width":0.0066489363,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"More…","depth":6,"bounds":{"left":0.50299203,"top":0.3719074,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"More","depth":8,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.008976064,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.0033244682,"height":0.011173184}},{"char_start":1,"char_count":3,"bounds":{"left":0.5106383,"top":0.4094174,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXStaticText","text":"Unreads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Threads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Huddles","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Drafts & sent","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Directories","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-backend-engineers","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-inner-team","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ai-chapter","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"alerts","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"backend","depth":15,"bounds":{"left":0.5422208,"top":0.09736632,"width":0.018284574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.09736632,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54521275,"top":0.09736632,"width":0.015292553,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"bugs","depth":15,"bounds":{"left":0.5422208,"top":0.11971269,"width":0.010638298,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.11971269,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":3,"bounds":{"left":0.54521275,"top":0.11971269,"width":0.00731383,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"confusion-clinic","depth":15,"bounds":{"left":0.5422208,"top":0.14205906,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.14205906,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54454786,"top":0.14205906,"width":0.032247342,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"donut_time","depth":15,"bounds":{"left":0.5422208,"top":0.16440542,"width":0.025265958,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.16440542,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54521275,"top":0.16440542,"width":0.022273935,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"engineering","depth":15,"bounds":{"left":0.5422208,"top":0.1867518,"width":0.025930852,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.1867518,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":10,"bounds":{"left":0.54488033,"top":0.1867518,"width":0.022938829,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"general","depth":15,"bounds":{"left":0.5422208,"top":0.20909816,"width":0.016289894,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.20909816,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54488033,"top":0.20909816,"width":0.013297873,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"happy_birthday","depth":15,"bounds":{"left":0.5422208,"top":0.23144454,"width":0.033909574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.23144454,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.54521275,"top":0.23144454,"width":0.030917553,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infosec_internal_all","depth":15,"bounds":{"left":0.5422208,"top":0.25379092,"width":0.041888297,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.25379092,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":19,"bounds":{"left":0.54355055,"top":0.25379092,"width":0.040226065,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infra-changes","depth":15,"bounds":{"left":0.5422208,"top":0.27613726,"width":0.029587766,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.27613726,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54355055,"top":0.27613726,"width":0.02825798,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infrastructure_dev","depth":15,"bounds":{"left":0.5422208,"top":0.29848364,"width":0.040226065,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.29848364,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":17,"bounds":{"left":0.54355055,"top":0.29848364,"width":0.038896278,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"jbu-team-info","depth":15,"bounds":{"left":0.5422208,"top":0.32083002,"width":0.029920213,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.32083002,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54355055,"top":0.32083002,"width":0.028590426,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"jiminny-bg","depth":15,"bounds":{"left":0.5422208,"top":0.34317636,"width":0.023271276,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.34317636,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54355055,"top":0.34317636,"width":0.021609042,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"platform-team","depth":15,"bounds":{"left":0.5422208,"top":0.36552274,"width":0.03158245,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.36552274,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54521275,"top":0.36552274,"width":0.028590426,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"platform-tickets","depth":15,"bounds":{"left":0.5422208,"top":0.38786912,"width":0.034906916,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.38786912,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54521275,"top":0.38786912,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"product_launches","depth":15,"bounds":{"left":0.5422208,"top":0.4102155,"width":0.03856383,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.4102155,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54521275,"top":0.4102155,"width":0.03557181,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"random","depth":15,"bounds":{"left":0.5422208,"top":0.43256184,"width":0.016954787,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.43256184,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":5,"bounds":{"left":0.54421544,"top":0.43256184,"width":0.014960106,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"releases","depth":15,"bounds":{"left":0.5422208,"top":0.45490822,"width":0.018284574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.45490822,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":7,"bounds":{"left":0.54421544,"top":0.45490822,"width":0.016289894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"support","depth":15,"bounds":{"left":0.5422208,"top":0.4772546,"width":0.017287234,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.4772546,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54454786,"top":0.4772546,"width":0.01462766,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"thank-yous","depth":15,"bounds":{"left":0.5422208,"top":0.49960095,"width":0.024601065,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.49960095,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54421544,"top":0.49960095,"width":0.022606382,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"the_people_of_jiminny","depth":15,"bounds":{"left":0.5422208,"top":0.5219473,"width":0.045212764,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5219473,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":20,"bounds":{"left":0.54421544,"top":0.5219473,"width":0.04720745,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Vasil Vasilev","depth":15,"bounds":{"left":0.5422208,"top":0.5746209,"width":0.026595745,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5746209,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54521275,"top":0.5746209,"width":0.023271276,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Stefka Stoyanova","depth":15,"bounds":{"left":0.5422208,"top":0.5969673,"width":0.037898935,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5969673,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54488033,"top":0.5969673,"width":0.03523936,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Iliyana Netseva","depth":15,"bounds":{"left":0.5422208,"top":0.61931366,"width":0.03324468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.61931366,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54355055,"top":0.61931366,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Stoyan Tomov","depth":15,"bounds":{"left":0.5422208,"top":0.64166003,"width":0.030917553,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.64166003,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":11,"bounds":{"left":0.54488033,"top":0.64166003,"width":0.027925532,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Petko Kashinski","depth":15,"bounds":{"left":0.5422208,"top":0.6640064,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.6640064,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54521275,"top":0.6640064,"width":0.03158245,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Galya Dimitrova","depth":15,"bounds":{"left":0.5422208,"top":0.6863527,"width":0.03523936,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.6863527,"width":0.003656915,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54587764,"top":0.6863527,"width":0.03158245,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Todor Stamatov","depth":15,"bounds":{"left":0.5422208,"top":0.7086991,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7086991,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.54454786,"top":0.7086991,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Steliyan Georgiev","depth":15,"bounds":{"left":0.5422208,"top":0.7310455,"width":0.038231384,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7310455,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":16,"bounds":{"left":0.54488033,"top":0.7310455,"width":0.03557181,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Ves","depth":15,"bounds":{"left":0.5422208,"top":0.75339186,"width":0.007978723,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.75339186,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":2,"bounds":{"left":0.54521275,"top":0.75339186,"width":0.004986702,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Mira","depth":15,"bounds":{"left":0.5422208,"top":0.77573824,"width":0.010305851,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.77573824,"width":0.004654255,"height":0.014365523}},{"char_start":1,"char_count":3,"bounds":{"left":0.546875,"top":0.77573824,"width":0.005319149,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Nikolay Yankov","depth":15,"bounds":{"left":0.5422208,"top":0.7980846,"width":0.032912236,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7980846,"width":0.0039893617,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.5462101,"top":0.7980846,"width":0.028922873,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"James Graham","depth":15,"bounds":{"left":0.5422208,"top":0.820431,"width":0.031914894,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.820431,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":11,"bounds":{"left":0.54421544,"top":0.820431,"width":0.029920213,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Lukas Kovalik","depth":15,"bounds":{"left":0.5422208,"top":0.8427773,"width":0.029587766,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.8427773,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54488033,"top":0.8427773,"width":0.026928192,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"you","depth":15,"bounds":{"left":0.5744681,"top":0.8427773,"width":0.0063164895,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5744681,"top":0.8427773,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":2,"bounds":{"left":0.5767952,"top":0.8427773,"width":0.0056515955,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Jira Cloud","depth":15,"bounds":{"left":0.5422208,"top":0.8954509,"width":0.021941489,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.8954509,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54421544,"top":0.8954509,"width":0.019946808,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Toast","depth":15,"bounds":{"left":0.5422208,"top":0.91779727,"width":0.011635638,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.91779727,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":4,"bounds":{"left":0.54454786,"top":0.91779727,"width":0.00930851,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Google Calendar","depth":15,"bounds":{"left":0.5422208,"top":0.94014364,"width":0.030585106,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.94014364,"width":0.003656915,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54587764,"top":0.94014364,"width":0.032912236,"height":0.014365523}}],"role_description":"text"},{"role":"AXRadioButton","text":"Messages","depth":9,"bounds":{"left":0.60206115,"top":0.09177973,"width":0.030917553,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Messages","depth":11,"bounds":{"left":0.61136967,"top":0.10055866,"width":0.018949468,"height":0.012769354},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.61136967,"top":0.10055866,"width":0.0039893617,"height":0.012769354}},{"char_start":1,"char_count":7,"bounds":{"left":0.61535907,"top":0.10055866,"width":0.014960106,"height":0.012769354}}],"role_description":"text"},{"role":"AXRadioButton","text":"Add canvas","depth":10,"bounds":{"left":0.63397604,"top":0.09177973,"width":0.034242023,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Add canvas","depth":12,"bounds":{"left":0.64328456,"top":0.10055866,"width":0.022273935,"height":0.012769354},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.64328456,"top":0.10055866,"width":0.0033244682,"height":0.012769354}},{"char_start":1,"char_count":9,"bounds":{"left":0.6462766,"top":0.10055866,"width":0.019281914,"height":0.012769354}}],"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":9,"bounds":{"left":0.66921544,"top":0.09177973,"width":0.020944148,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":11,"bounds":{"left":0.67852396,"top":0.10055866,"width":0.008976064,"height":0.012769354},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Pins","depth":9,"bounds":{"left":0.69148934,"top":0.09177973,"width":0.020279255,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Pins","depth":11,"bounds":{"left":0.70079786,"top":0.10055866,"width":0.00831117,"height":0.012769354},"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Add and Edit Channel Tabs","depth":9,"bounds":{"left":0.71276593,"top":0.09177973,"width":0.010970744,"height":0.030327214},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Canvas","depth":9,"bounds":{"left":0.59640956,"top":0.0518755,"width":0.015957447,"height":0.0007980846},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"List","depth":9,"bounds":{"left":0.59640956,"top":0.0518755,"width":0.007978723,"height":0.0007980846},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Folder","depth":9,"bounds":{"left":0.59640956,"top":0.0518755,"width":0.013962766,"height":0.0007980846},"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Jump to date","depth":14,"bounds":{"left":0.7849069,"top":0.12689546,"width":0.025265958,"height":0.022346368},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Today at 12:00:37 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"малко по късно и на мен ще ми трябва ревю за един голям feature","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:46 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"но ще ти пиша, като е готов за гледане","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(edited)","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:11:37 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:11 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ок , mersi","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:23:53 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:23 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"като имаш време, разгледай този интересен ПР:","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"https://github.com/jiminny/app/pull/12130","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"https://github.com/jiminny/app/pull/12130","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:25:05 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:25","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:25:47 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:25","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:26:15 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:26","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:12 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Не знам това дали е релевантно","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:14 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1.","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Shared Elasticsearch Sockets:","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Because","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"pcntl_fork()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"resetAfterFork()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"cURL","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"exceptions.","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"2.","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Supervisor Shutdown Deadlock:","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"In","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"reapChildren()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":", calling","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"pcntl_waitpid()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"without the","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"WNOHANG","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(edited)","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:29 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
4724382746562927558
|
222267811012514398
|
idle
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки
Today at 1:25:47 PM
1:25
процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип
Today at 1:26:15 PM
1:26
и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity
Lukas Kovalik
Today at 2:45:12 PM
2:45 PM
Не знам това дали е релевантно
Today at 2:45:14 PM
2:45
1.
Shared Elasticsearch Sockets:
Because
pcntl_fork()
clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in
resetAfterFork()
(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and
cURL
exceptions.
2.
Supervisor Shutdown Deadlock:
In
reapChildren()
, calling
pcntl_waitpid()
without the
WNOHANG
flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.
(edited)
Today at 2:45:29 PM
SIUCKWindowHelpPwovscors#12121 on JY-20963-folproidetecanyice pn.he bolbees.phe©ActivityControlier.php© VoiceConsentPrefix.phpNotificationsnObservers© AccountObserver.phpCyActwwooserver.pnp© ContactObserver.phpGroupObserver.pho© LeadObserver.phoC ProfileObserver.phpC SocialAccountObserver.phg© UserObserver.pho© UserRoleObserver.phc(in Policie:aProviders• Queuea Reoositonea RulesaServicesDa ActivityAiReodrleallendarConnerimermobiacte@ DecorateActivityDummym Helnarsv D Hubspor(i) AccountSyncStrategyMAetioneMcontctSwnestrateon• D DTO› FieldsThtauendOLekоkyseiwico.onOAeindi.oneMWiaKorCass wochexeOpportunivsvncstratcov- Pac nation- Prosoec-SearchStrateo→- RedisService traits• Utils- Wechookc) Batchsunceo ector cho© BatchSvncRedisService.oCleantono@ GiosedDealStaapsSeniceclnaalise rccarica ono* Breturn T The result of the APi callprivate function executeRequest(callable SapiCall)ScacheKey = Sthis->getRateLimitCacheKeyOScacheocxozresac = keozst.oet scachekeyif (is_string(ScachedExpiresAt) && is_numeric(ScachedExpiresAt)) 1Sremaining = naxl va(cint)) ScachedExpiresAt - tineon:hrow new kacetinzcexceoezonsrenaining,neruonSantwaittecarch leinronabieoi4 (Sthiso>isHubsootRateLinit(Se))thisosparse?erny.er e// NX: only the first job to receive a 429 in this burst sets the key.// Subsequent 42%s in the same burst leave the TTL untouched so theIl window is not reset by every concurrent job hitting the linit.Redis::set(ScacheKey, (string) (tine() + SretryAfter).options:'EX', SretryAfter, "NX*);Sthis->log->warning( Hubspot) Received 429 from API'. (iteanSdl'configid'= Sthis->config->getido.=) Sratmultten-ENAeMAONNATthrow new RateLinitException message: "Hubspot returned 429'. SretryAfter. Se):Throw Senprivate function getRateLinitCachekevO: strinol...;=custom.loglaravel.logA console [STAGING-782785704785786711[712713[PHONE]725727728729E732-733—730737- 738)TX: AUTONAND a.created_at › DATE_:GROUP BY u.id, u.email,ORDER BY sne count DESMselect + Eron teans, wherlselect + Eron coles,SELECTCONCATU.Id, CASE WHsa.*t.ouner id FROM sociJOIN users u on u.id = sJOIN teans tWHERE u.tean_id = 1117 aSELECT * FROM actávitioSELECT * FROM actávitioSELECT * FROM crn configSELECT # FROM teans WHERselleetron usens whenselect * fron playbooksseleetron miawhonkeselect * fron playbook_ctseleet ron eoeselect * fron crn_field.vSELECT * FROM crn_field_AOTM con Brelds 4 0M 4• JOIN activities a ON $NHERF Actvity "d = 7002AND € con onovider saSELECT * FROM activity.mselect * fron text relayselect * fron activitiesselect * fron users whenPARAtT GAAR MANGUREANOPAlRetGhAn dAAAIRdAMPolhnttene neard wharselect * fron teans wherPohattoon activtysHoeDMsActivityJiminnY …# backend# buescontusion-dinig# donut_time#enpineerine# general# hapoy birthdavA infocoe intemal all# infra-chansed# infrastructure de#bu-team-infoiliminnv-bo# platform-team# platform-ticketstoroduct launche# random# release# suppor# thank-youssie the neoole of fimill6? Direct message.Vasil VasilenF8. Stefka Stoyanova1a llivana NetsevaA Ctovan TomnulPetko KashinskiGola Nimitrous: Todor Stamatol1 Stelivan Georsie.&r MireNikolav Vanko&. James GrahamLukas Kovalky7o0sLXInu co moy to:loide@ Describe what you are looking forVasil Vasileve MessagerNeRdd canvfiles.Vasil Vasilev 2:56 PM1 с добър коментарDoory2e intentionaЗ сьщо e intentional поради факта, че phpredis dniver-a не поддьржа set ex +nх параметри, и тряова да се пуснат две операции set + expireLukas Kovalik 3.07 PMок. зз по пуснах пак поез gеminіlза третата точка обаче наистина ли няма подьржкааз май си ги ползвам някьлеVasil Vasilev 3:10 PMне става, бях го направил така, и се счупиLukas Kovalik 3:10 PMами и при мен се чумешеVasil Vasilev 3:11 PMpredis поддьржа set(Skey. Svalue. nx' - true, ex =60)Cnhnranic He caRaLukas Kovalik 3.14pNтака май не работеше Sresult = Redis:set(StestKey, StestValue, 'EX, Stti, "NX"): а така да Sresult = Redis:set(StestKey, StestValue, ['nx, "ex' => $ttl]);Vasil Vasiley 2.11 pwLukas Kovalik 3.12 pNне помно BеUEVasil Vasilev 3:12 PMobоитноtо може naeLukas Kovalik 3-12 PMможе и ла брькамVacil Vaciley 242 pwewons uusSlockAcquired - Redis::set(self::POLLING LOCK KEY, ison encode(SlockData). "EX', self::LOCK TTL SECONDS. *NX*))значи пьрвото работиLukas Kovalik 313 PMwe to ononnsmeдn:...
|
85253
|
NULL
|
NULL
|
NULL
|
|
85254
|
2920
|
6
|
2026-05-28T12:14:59.866678+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970499866_m1.jpg...
|
Slack
|
Vasil Vasilev (DM) - Jiminny Inc - 3 new items - S Vasil Vasilev (DM) - Jiminny Inc - 3 new items - Slack...
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки
Today at 1:25:47 PM
1:25
процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип
Today at 1:26:15 PM
1:26
и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity
Lukas Kovalik
Today at 2:45:12 PM
2:45 PM
Не знам това дали е релевантно
Today at 2:45:14 PM
2:45
1.
Shared Elasticsearch Sockets:
Because
pcntl_fork()
clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in
resetAfterFork()
(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and
cURL
exceptions.
2.
Supervisor Shutdown Deadlock:
In
reapChildren()
, calling
pcntl_waitpid()
without the
WNOHANG
flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.
(edited)
Today at 2:45:29 PM
2:45
3.
Non-Atomic Redis Locks:
The new
ReindexTargetStatsReporter
checks the lock with
get
and then creates it with
set
. Because the workers are truly parallel, they can both read
null
at the exact same microsecond and both push duplicate metrics to Datadog. This needs to be a single, atomic command (e.g.,
set
with
NX
).
Vasil Vasilev
Today at 2:56:52 PM
2:56 PM
1 e добър коментар,
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions
Today at 2:56:55 PM
2:56
2 е intentional,
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Later","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Later","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"More…","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"More","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Unreads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Threads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Huddles","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Drafts & sent","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Directories","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-backend-engineers","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-inner-team","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ai-chapter","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"alerts","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"backend","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"bugs","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"confusion-clinic","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"donut_time","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"engineering","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"general","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"happy_birthday","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infosec_internal_all","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infra-changes","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infrastructure_dev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"jbu-team-info","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"jiminny-bg","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"platform-team","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"platform-tickets","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"product_launches","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"random","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"releases","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"support","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"thank-yous","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"the_people_of_jiminny","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Vasil Vasilev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Stefka Stoyanova","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Iliyana Netseva","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Stoyan Tomov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Petko Kashinski","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Galya Dimitrova","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Todor Stamatov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Steliyan Georgiev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Ves","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Mira","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Nikolay Yankov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"James Graham","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Lukas Kovalik","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"you","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Jira Cloud","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Toast","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Google Calendar","depth":15,"bounds":{"left":0.56805557,"top":0.0,"width":0.06388889,"height":0.02},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.56805557,"top":0.0,"width":0.007638889,"height":0.02}},{"char_start":1,"char_count":14,"bounds":{"left":0.57569444,"top":0.0,"width":0.06875,"height":0.02}}],"role_description":"text"},{"role":"AXRadioButton","text":"Messages","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Messages","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Add canvas","depth":10,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Add canvas","depth":12,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Pins","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Pins","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Add and Edit Channel Tabs","depth":9,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Canvas","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"List","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Folder","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Jump to date","depth":14,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Today at 12:00:37 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"малко по късно и на мен ще ми трябва ревю за един голям feature","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:46 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"но ще ти пиша, като е готов за гледане","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(edited)","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:11:37 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:11 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ок , mersi","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:23:53 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:23 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"като имаш време, разгледай този интересен ПР:","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"https://github.com/jiminny/app/pull/12130","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"https://github.com/jiminny/app/pull/12130","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:25:05 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:25","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:25:47 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:25","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:26:15 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:26","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:12 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Не знам това дали е релевантно","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:14 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1.","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Shared Elasticsearch Sockets:","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Because","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"pcntl_fork()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"resetAfterFork()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"cURL","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"exceptions.","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"2.","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Supervisor Shutdown Deadlock:","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"In","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"reapChildren()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":", calling","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"pcntl_waitpid()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"without the","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"WNOHANG","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(edited)","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:29 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"3.","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Non-Atomic Redis Locks:","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"The new","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ReindexTargetStatsReporter","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"checks the lock with","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"get","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"and then creates it with","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"set","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":". Because the workers are truly parallel, they can both read","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"null","depth":17,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"at the exact same microsecond and both push duplicate metrics to Datadog. This needs to be a single, atomic command (e.g.,","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"set","depth":17,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"with","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"NX","depth":17,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":").","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXLink","text":"Today at 2:56:52 PM","depth":15,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:56 PM","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1 e добър коментар,","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"React with white_check_mark","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with eyes","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with raised_hands","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Add reaction…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Reply in thread","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Forward message…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Save for later","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXPopUpButton","text":"More actions","depth":17,"on_screen":false,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Today at 2:56:55 PM","depth":16,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:56","depth":17,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"2 е intentional,","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"React with white_check_mark","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with eyes","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with raised_hands","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Add reaction…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Reply in thread","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Forward message…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Save for later","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXPopUpButton","text":"More actions","depth":17,"on_screen":false,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-6870836034846583390
|
-2155054586562104738
|
visual_change
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки
Today at 1:25:47 PM
1:25
процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип
Today at 1:26:15 PM
1:26
и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity
Lukas Kovalik
Today at 2:45:12 PM
2:45 PM
Не знам това дали е релевантно
Today at 2:45:14 PM
2:45
1.
Shared Elasticsearch Sockets:
Because
pcntl_fork()
clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in
resetAfterFork()
(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and
cURL
exceptions.
2.
Supervisor Shutdown Deadlock:
In
reapChildren()
, calling
pcntl_waitpid()
without the
WNOHANG
flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.
(edited)
Today at 2:45:29 PM
2:45
3.
Non-Atomic Redis Locks:
The new
ReindexTargetStatsReporter
checks the lock with
get
and then creates it with
set
. Because the workers are truly parallel, they can both read
null
at the exact same microsecond and both push duplicate metrics to Datadog. This needs to be a single, atomic command (e.g.,
set
with
NX
).
Vasil Vasilev
Today at 2:56:52 PM
2:56 PM
1 e добър коментар,
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions
Today at 2:56:55 PM
2:56
2 е intentional,
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions
PhpStormFileEditViewNavigateCodeRefactorRunToolsGitWindowHelpec2-user@ip-10-30-129-190:~screenpipe"O ₴4‹$0(ah]A100% <78• Thu 28 May 15:14:59181ec2-user@ip-10-30-140-...₴7DOCKER#_####_#####\\###||\#/V~'881DEV (-zsh)O [EMAIL] Linux 2023 (ECS Optimized)_/m/For documentation, visit [URL_WITH_CREDENTIALS] ~]$ exitlogoutConnection to jiminny-prod-ecsi closed.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ applukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ vprodWarning: Permanently added 'jiminny-prod-ecs1' (ED25519) to the list of known hosts.A newer release of "Amazon Linux" is available.Version 2023.10.20260330:Version 2023.11.20260406:Version 2023.11.20260413:Version2023.11.20260427:Version2023.11.20260505:Version 2023.11.20260509:Version 2023.11.20260511:Version 2023.11.20260514:Run "/usr/bin/dnf check-release-update" for full release and version update info#_~\ ####_\ #####\\###1\#/Amazon Linux 2023 (ECS Optimized)/m/'For documentation, visit [URL_WITH_CREDENTIALS] ~]$ client_loop: send disconnect: Broken pipeukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-relay) $I...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85253
|
2921
|
6
|
2026-05-28T12:14:58.317508+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970498317_m2.jpg...
|
Slack
|
Vasil Vasilev (DM) - Jiminny Inc - 3 new items - S Vasil Vasilev (DM) - Jiminny Inc - 3 new items - Slack...
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки
Today at 1:25:47 PM
1:25
процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип
Today at 1:26:15 PM
1:26
и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity
Lukas Kovalik
Today at 2:45:12 PM
2:45 PM
Не знам това дали е релевантно
Today at 2:45:14 PM
2:45
1.
Shared Elasticsearch Sockets:
Because
pcntl_fork()
clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in
resetAfterFork()
(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and
cURL
exceptions.
2.
Supervisor Shutdown Deadlock:
In
reapChildren()
, calling
pcntl_waitpid()
without the
WNOHANG
flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.
(edited)
Today at 2:45:29 PM
2:45
3.
Non-Atomic Redis Locks:
The new
ReindexTargetStatsReporter
checks the lock with
get
and then creates it with
set
. Because the workers are truly parallel, they can both read
null
at the exact same microsecond and both push duplicate metrics to Datadog. This needs to be a single, atomic command (e.g.,
set
with
NX
).
Vasil Vasilev
Today at 2:56:52 PM
2:56 PM
1 e добър коментар,
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions
Today at 2:56:55 PM
2:56
2 е intentional,
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions
Today at 2:57:50 PM
2:57
3 също е intentional поради факта, че phpredis driver-a не поддържа set ex +nx параметри, и трябва да се пуснат две операции set + expire
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"bounds":{"left":0.5056516,"top":0.058260176,"width":0.011968086,"height":0.028731046},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"bounds":{"left":0.50299203,"top":0.10055866,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"bounds":{"left":0.50664896,"top":0.13806863,"width":0.009973404,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"bounds":{"left":0.50299203,"top":0.15482841,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":8,"bounds":{"left":0.50764626,"top":0.19233839,"width":0.007978723,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":6,"bounds":{"left":0.50299203,"top":0.20909816,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":8,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.012965426,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.0026595744,"height":0.011173184}},{"char_start":1,"char_count":7,"bounds":{"left":0.50764626,"top":0.24660814,"width":0.010638298,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":6,"bounds":{"left":0.50299203,"top":0.26336792,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":8,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0076462766,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5099734,"top":0.3008779,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Later","depth":6,"bounds":{"left":0.50299203,"top":0.31763768,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Later","depth":8,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.008643617,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5093085,"top":0.35514766,"width":0.0066489363,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"More…","depth":6,"bounds":{"left":0.50299203,"top":0.3719074,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"More","depth":8,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.008976064,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.0033244682,"height":0.011173184}},{"char_start":1,"char_count":3,"bounds":{"left":0.5106383,"top":0.4094174,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXStaticText","text":"Unreads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Threads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Huddles","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Drafts & sent","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Directories","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-backend-engineers","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-inner-team","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ai-chapter","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"alerts","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"backend","depth":15,"bounds":{"left":0.5422208,"top":0.09736632,"width":0.018284574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.09736632,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54521275,"top":0.09736632,"width":0.015292553,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"bugs","depth":15,"bounds":{"left":0.5422208,"top":0.11971269,"width":0.010638298,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.11971269,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":3,"bounds":{"left":0.54521275,"top":0.11971269,"width":0.00731383,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"confusion-clinic","depth":15,"bounds":{"left":0.5422208,"top":0.14205906,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.14205906,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54454786,"top":0.14205906,"width":0.032247342,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"donut_time","depth":15,"bounds":{"left":0.5422208,"top":0.16440542,"width":0.025265958,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.16440542,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54521275,"top":0.16440542,"width":0.022273935,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"engineering","depth":15,"bounds":{"left":0.5422208,"top":0.1867518,"width":0.025930852,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.1867518,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":10,"bounds":{"left":0.54488033,"top":0.1867518,"width":0.022938829,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"general","depth":15,"bounds":{"left":0.5422208,"top":0.20909816,"width":0.016289894,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.20909816,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54488033,"top":0.20909816,"width":0.013297873,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"happy_birthday","depth":15,"bounds":{"left":0.5422208,"top":0.23144454,"width":0.033909574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.23144454,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.54521275,"top":0.23144454,"width":0.030917553,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infosec_internal_all","depth":15,"bounds":{"left":0.5422208,"top":0.25379092,"width":0.041888297,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.25379092,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":19,"bounds":{"left":0.54355055,"top":0.25379092,"width":0.040226065,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infra-changes","depth":15,"bounds":{"left":0.5422208,"top":0.27613726,"width":0.029587766,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.27613726,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54355055,"top":0.27613726,"width":0.02825798,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infrastructure_dev","depth":15,"bounds":{"left":0.5422208,"top":0.29848364,"width":0.040226065,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.29848364,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":17,"bounds":{"left":0.54355055,"top":0.29848364,"width":0.038896278,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"jbu-team-info","depth":15,"bounds":{"left":0.5422208,"top":0.32083002,"width":0.029920213,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.32083002,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54355055,"top":0.32083002,"width":0.028590426,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"jiminny-bg","depth":15,"bounds":{"left":0.5422208,"top":0.34317636,"width":0.023271276,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.34317636,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54355055,"top":0.34317636,"width":0.021609042,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"platform-team","depth":15,"bounds":{"left":0.5422208,"top":0.36552274,"width":0.03158245,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.36552274,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54521275,"top":0.36552274,"width":0.028590426,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"platform-tickets","depth":15,"bounds":{"left":0.5422208,"top":0.38786912,"width":0.034906916,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.38786912,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54521275,"top":0.38786912,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"product_launches","depth":15,"bounds":{"left":0.5422208,"top":0.4102155,"width":0.03856383,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.4102155,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54521275,"top":0.4102155,"width":0.03557181,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"random","depth":15,"bounds":{"left":0.5422208,"top":0.43256184,"width":0.016954787,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.43256184,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":5,"bounds":{"left":0.54421544,"top":0.43256184,"width":0.014960106,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"releases","depth":15,"bounds":{"left":0.5422208,"top":0.45490822,"width":0.018284574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.45490822,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":7,"bounds":{"left":0.54421544,"top":0.45490822,"width":0.016289894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"support","depth":15,"bounds":{"left":0.5422208,"top":0.4772546,"width":0.017287234,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.4772546,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54454786,"top":0.4772546,"width":0.01462766,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"thank-yous","depth":15,"bounds":{"left":0.5422208,"top":0.49960095,"width":0.024601065,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.49960095,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54421544,"top":0.49960095,"width":0.022606382,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"the_people_of_jiminny","depth":15,"bounds":{"left":0.5422208,"top":0.5219473,"width":0.045212764,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5219473,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":20,"bounds":{"left":0.54421544,"top":0.5219473,"width":0.04720745,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Vasil Vasilev","depth":15,"bounds":{"left":0.5422208,"top":0.5746209,"width":0.026595745,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5746209,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54521275,"top":0.5746209,"width":0.023271276,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Stefka Stoyanova","depth":15,"bounds":{"left":0.5422208,"top":0.5969673,"width":0.037898935,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5969673,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54488033,"top":0.5969673,"width":0.03523936,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Iliyana Netseva","depth":15,"bounds":{"left":0.5422208,"top":0.61931366,"width":0.03324468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.61931366,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54355055,"top":0.61931366,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Stoyan Tomov","depth":15,"bounds":{"left":0.5422208,"top":0.64166003,"width":0.030917553,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.64166003,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":11,"bounds":{"left":0.54488033,"top":0.64166003,"width":0.027925532,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Petko Kashinski","depth":15,"bounds":{"left":0.5422208,"top":0.6640064,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.6640064,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54521275,"top":0.6640064,"width":0.03158245,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Galya Dimitrova","depth":15,"bounds":{"left":0.5422208,"top":0.6863527,"width":0.03523936,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.6863527,"width":0.003656915,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54587764,"top":0.6863527,"width":0.03158245,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Todor Stamatov","depth":15,"bounds":{"left":0.5422208,"top":0.7086991,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7086991,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.54454786,"top":0.7086991,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Steliyan Georgiev","depth":15,"bounds":{"left":0.5422208,"top":0.7310455,"width":0.038231384,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7310455,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":16,"bounds":{"left":0.54488033,"top":0.7310455,"width":0.03557181,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Ves","depth":15,"bounds":{"left":0.5422208,"top":0.75339186,"width":0.007978723,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.75339186,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":2,"bounds":{"left":0.54521275,"top":0.75339186,"width":0.004986702,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Mira","depth":15,"bounds":{"left":0.5422208,"top":0.77573824,"width":0.010305851,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.77573824,"width":0.004654255,"height":0.014365523}},{"char_start":1,"char_count":3,"bounds":{"left":0.546875,"top":0.77573824,"width":0.005319149,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Nikolay Yankov","depth":15,"bounds":{"left":0.5422208,"top":0.7980846,"width":0.032912236,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7980846,"width":0.0039893617,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.5462101,"top":0.7980846,"width":0.028922873,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"James Graham","depth":15,"bounds":{"left":0.5422208,"top":0.820431,"width":0.031914894,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.820431,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":11,"bounds":{"left":0.54421544,"top":0.820431,"width":0.029920213,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Lukas Kovalik","depth":15,"bounds":{"left":0.5422208,"top":0.8427773,"width":0.029587766,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.8427773,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54488033,"top":0.8427773,"width":0.026928192,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"you","depth":15,"bounds":{"left":0.5744681,"top":0.8427773,"width":0.0063164895,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5744681,"top":0.8427773,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":2,"bounds":{"left":0.5767952,"top":0.8427773,"width":0.0056515955,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Jira Cloud","depth":15,"bounds":{"left":0.5422208,"top":0.8954509,"width":0.021941489,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.8954509,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54421544,"top":0.8954509,"width":0.019946808,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Toast","depth":15,"bounds":{"left":0.5422208,"top":0.91779727,"width":0.011635638,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.91779727,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":4,"bounds":{"left":0.54454786,"top":0.91779727,"width":0.00930851,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Google Calendar","depth":15,"bounds":{"left":0.5422208,"top":0.94014364,"width":0.030585106,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.94014364,"width":0.003656915,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54587764,"top":0.94014364,"width":0.032912236,"height":0.014365523}}],"role_description":"text"},{"role":"AXRadioButton","text":"Messages","depth":9,"bounds":{"left":0.60206115,"top":0.09177973,"width":0.030917553,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Messages","depth":11,"bounds":{"left":0.61136967,"top":0.10055866,"width":0.018949468,"height":0.012769354},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.61136967,"top":0.10055866,"width":0.0039893617,"height":0.012769354}},{"char_start":1,"char_count":7,"bounds":{"left":0.61535907,"top":0.10055866,"width":0.014960106,"height":0.012769354}}],"role_description":"text"},{"role":"AXRadioButton","text":"Add canvas","depth":10,"bounds":{"left":0.63397604,"top":0.09177973,"width":0.034242023,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Add canvas","depth":12,"bounds":{"left":0.64328456,"top":0.10055866,"width":0.022273935,"height":0.012769354},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.64328456,"top":0.10055866,"width":0.0033244682,"height":0.012769354}},{"char_start":1,"char_count":9,"bounds":{"left":0.6462766,"top":0.10055866,"width":0.019281914,"height":0.012769354}}],"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":9,"bounds":{"left":0.66921544,"top":0.09177973,"width":0.020944148,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":11,"bounds":{"left":0.67852396,"top":0.10055866,"width":0.008976064,"height":0.012769354},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Pins","depth":9,"bounds":{"left":0.69148934,"top":0.09177973,"width":0.020279255,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Pins","depth":11,"bounds":{"left":0.70079786,"top":0.10055866,"width":0.00831117,"height":0.012769354},"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Add and Edit Channel Tabs","depth":9,"bounds":{"left":0.71276593,"top":0.09177973,"width":0.010970744,"height":0.030327214},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Canvas","depth":9,"bounds":{"left":0.59640956,"top":0.0518755,"width":0.015957447,"height":0.0007980846},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"List","depth":9,"bounds":{"left":0.59640956,"top":0.0518755,"width":0.007978723,"height":0.0007980846},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Folder","depth":9,"bounds":{"left":0.59640956,"top":0.0518755,"width":0.013962766,"height":0.0007980846},"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Jump to date","depth":14,"bounds":{"left":0.7849069,"top":0.12689546,"width":0.025265958,"height":0.022346368},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Today at 12:00:37 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"малко по късно и на мен ще ми трябва ревю за един голям feature","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:46 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"но ще ти пиша, като е готов за гледане","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(edited)","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:11:37 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:11 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ок , mersi","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:23:53 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:23 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"като имаш време, разгледай този интересен ПР:","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"https://github.com/jiminny/app/pull/12130","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"https://github.com/jiminny/app/pull/12130","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:25:05 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:25","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:25:47 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:25","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:26:15 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:26","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:12 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Не знам това дали е релевантно","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:14 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1.","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Shared Elasticsearch Sockets:","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Because","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"pcntl_fork()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"resetAfterFork()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"cURL","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"exceptions.","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"2.","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Supervisor Shutdown Deadlock:","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"In","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"reapChildren()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":", calling","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"pcntl_waitpid()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"without the","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"WNOHANG","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(edited)","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:29 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"3.","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Non-Atomic Redis Locks:","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"The new","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ReindexTargetStatsReporter","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"checks the lock with","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"get","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"and then creates it with","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"set","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":". Because the workers are truly parallel, they can both read","depth":16,"bounds":{"left":0.6180186,"top":0.11572227,"width":0.37300533,"height":0.0071827616},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"null","depth":17,"bounds":{"left":0.64162236,"top":0.11572227,"width":0.009640957,"height":0.0071827616},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"at the exact same microsecond and both push duplicate metrics to Datadog. This needs to be a single, atomic command (e.g.,","depth":16,"bounds":{"left":0.6525931,"top":0.11572227,"width":0.27393618,"height":0.0071827616},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"set","depth":17,"bounds":{"left":0.9275266,"top":0.11572227,"width":0.00731383,"height":0.0071827616},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"with","depth":16,"bounds":{"left":0.9361702,"top":0.11572227,"width":0.012300532,"height":0.0071827616},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"NX","depth":17,"bounds":{"left":0.9494681,"top":0.11572227,"width":0.004986702,"height":0.0071827616},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":").","depth":16,"bounds":{"left":0.95578456,"top":0.11572227,"width":0.0026595744,"height":0.0071827616},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"bounds":{"left":0.6180186,"top":0.13088587,"width":0.027593086,"height":0.017557861},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"bounds":{"left":0.6456117,"top":0.13248204,"width":0.0026595744,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXLink","text":"Today at 2:56:52 PM","depth":15,"bounds":{"left":0.64793885,"top":0.1348763,"width":0.015292553,"height":0.011173184},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:56 PM","depth":16,"bounds":{"left":0.64793885,"top":0.1348763,"width":0.015292553,"height":0.011173184},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1 e добър коментар,","depth":16,"bounds":{"left":0.6180186,"top":0.15003991,"width":0.04720745,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"React with white_check_mark","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with eyes","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with raised_hands","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Add reaction…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Reply in thread","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Forward message…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Save for later","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXPopUpButton","text":"More actions","depth":17,"on_screen":false,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Today at 2:56:55 PM","depth":16,"bounds":{"left":0.60738033,"top":0.1763767,"width":0.007978723,"height":0.011173184},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:56","depth":17,"bounds":{"left":0.60738033,"top":0.1763767,"width":0.007978723,"height":0.011173184},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"2 е intentional,","depth":16,"bounds":{"left":0.6180186,"top":0.17398244,"width":0.032912236,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"React with white_check_mark","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with eyes","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with raised_hands","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Add reaction…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Reply in thread","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Forward message…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Save for later","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXPopUpButton","text":"More actions","depth":17,"on_screen":false,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Today at 2:57:50 PM","depth":16,"bounds":{"left":0.60738033,"top":0.20031923,"width":0.007978723,"height":0.011173184},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:57","depth":17,"bounds":{"left":0.60738033,"top":0.20031923,"width":0.007978723,"height":0.011173184},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"3 също е intentional поради факта, че phpredis driver-a не поддържа set ex +nx параметри, и трябва да се пуснат две операции set + expire","depth":16,"bounds":{"left":0.6180186,"top":0.19792499,"width":0.32114363,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"React with white_check_mark","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with eyes","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with raised_hands","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Add reaction…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Reply in thread","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
1135089822123404221
|
-1569621823671070626
|
visual_change
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки
Today at 1:25:47 PM
1:25
процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип
Today at 1:26:15 PM
1:26
и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity
Lukas Kovalik
Today at 2:45:12 PM
2:45 PM
Не знам това дали е релевантно
Today at 2:45:14 PM
2:45
1.
Shared Elasticsearch Sockets:
Because
pcntl_fork()
clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in
resetAfterFork()
(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and
cURL
exceptions.
2.
Supervisor Shutdown Deadlock:
In
reapChildren()
, calling
pcntl_waitpid()
without the
WNOHANG
flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.
(edited)
Today at 2:45:29 PM
2:45
3.
Non-Atomic Redis Locks:
The new
ReindexTargetStatsReporter
checks the lock with
get
and then creates it with
set
. Because the workers are truly parallel, they can both read
null
at the exact same microsecond and both push duplicate metrics to Datadog. This needs to be a single, atomic command (e.g.,
set
with
NX
).
Vasil Vasilev
Today at 2:56:52 PM
2:56 PM
1 e добър коментар,
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions
Today at 2:56:55 PM
2:56
2 е intentional,
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions
Today at 2:57:50 PM
2:57
3 също е intentional поради факта, че phpredis driver-a не поддържа set ex +nx параметри, и трябва да се пуснат две операции set + expire
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
SIUCKWindowHelpPwovscors#12121 on JY-20963-folproidetecanyice pn.he bolbees.phe©ActivityControlier.php© VoiceConsentPrefix.phpNotificationsnObservers© AccountObserver.phpCyActwwooserver.pnp© ContactObserver.phpGroupObserver.pho© LeadObserver.phoC ProfileObserver.phpC SocialAccountObserver.phg© UserObserver.pho© UserRoleObserver.phc(in Policie:aProviders• Queuea Reoositonea RulesaServicesDa ActivityAiReodrleallendarConnerimermobiacte@ DecorateActivityDummym Helnarsv D Hubspor(i) AccountSyncStrategyMAetioneMcontctSwnestrateon• D DTO› FieldsThtauendOLekоkyseiwico.onOAeindi.oneMWiaKorCass wochexeOpportunivsvncstratcov- Pac nation- Prosoec-SearchStrateo→- RedisService traits• Utils- Wechookc) Batchsunceo ector cho© BatchSvncRedisService.oCleantono@ GiosedDealStaapsSeniceclnaalise rccarica ono* Breturn T The result of the APi callprivate function executeRequest(callable SapiCall)ScacheKey = Sthis->getRateLimitCacheKeyOScacheocxozresac = keozst.oet scachekeyif (is_string(ScachedExpiresAt) && is_numeric(ScachedExpiresAt)) 1Sremaining = naxl va(cint)) ScachedExpiresAt - tineon:hrow new kacetinzcexceoezonsrenaining,neruonSantwaittecarch leinronabieoi4 (Sthiso>isHubsootRateLinit(Se))thisosparse?erny.er e// NX: only the first job to receive a 429 in this burst sets the key.// Subsequent 42%s in the same burst leave the TTL untouched so theIl window is not reset by every concurrent job hitting the linit.Redis::set(ScacheKey, (string) (tine() + SretryAfter).options:'EX', SretryAfter, "NX*);Sthis->log->warning( Hubspot) Received 429 from API'. (iteanSdl'configid'= Sthis->config->getido.=) Sratmultten-ENAeMAONNATthrow new RateLinitException message: "Hubspot returned 429'. SretryAfter. Se):Throw Senprivate function getRateLinitCachekevO: strinol...;=custom.loglaravel.logA console [STAGING-782785704785786711[712713[PHONE]725727728729E732-733—730737- 738)TX: AUTONAND a.created_at › DATE_:GROUP BY u.id, u.email,ORDER BY sne count DESMselect + Eron teans, wherlselect + Eron coles,SELECTCONCATU.Id, CASE WHsa.*t.ouner id FROM sociJOIN users u on u.id = sJOIN teans tWHERE u.tean_id = 1117 aSELECT * FROM actávitioSELECT * FROM actávitioSELECT * FROM crn configSELECT # FROM teans WHERselleetron usens whenselect * fron playbooksseleetron miawhonkeselect * fron playbook_ctseleet ron eoeselect * fron crn_field.vSELECT * FROM crn_field_AOTM con Brelds 4 0M 4• JOIN activities a ON $NHERF Actvity "d = 7002AND € con onovider saSELECT * FROM activity.mselect * fron text relayselect * fron activitiesselect * fron users whenPARAtT GAAR MANGUREANOPAlRetGhAn dAAAIRdAMPolhnttene neard wharselect * fron teans wherPohattoon activtysHoeDMsActivityJiminnY …# backend# buescontusion-dinig# donut_time#enpineerine# generall# hapoy birthdavA infocoe intemal all# infra-chansed# infrastructure de#bu-team-infoiliminnv-bo# platform-team# platform-ticketstoroduct launche# random# release# suppor# thank-youssie the neoole of fimill6? Direct message.Vasil VasilenF8. Stefka Stoyanova1a llivana NetsevaA Ctovan TomnulPetko KashinskiGola Nimitrous: Todor Stamatol1 Stelivan Georsie.&r MireNikolav Vanko&. James GrahamLukas Kovalky7o0sLXInu co woy 1o:14.00@ Describe what you are looking forVasil Vasileve MessagerNoR0d canvisfiles.+Vasil Vasilev 2:56 PM1 с добър коментарDoory2e intentionaЗ сьщо e intentional поради факта, че phpredis dniver-a не поддьржа set ex +nх параметри, и тряова да се пуснат две операции set + expireLukas Kovalik 3.07 PMок. зз по пуснах пак поез gеminіlза третата точка обаче наистина ли няма подьржкааз май си ги ползвам някьлеVasil Vasilev 3:10 PMне става, бях го направил така, и се счупиLukas Kovalik 3:10 PMами и при мен се чумешеVasil Vasilev 3:11 PMpredis поддьржа set(Skey. Svalue. nx' - true, ex =60)Cnhnranic He caRaLukas Kovalik 3.14pNтака май не работеше Sresult = Redis=set(Stestkey, StestValue, "ax, Sttl, "NX*); а така да Sresult = Redis:set(StestKey, StestValue, [nx, 'ex' => Sttl)):Vasil Vasiley 2.11 pwLukas Kovalik 3.12 pNне помно BеUEVasil Vasilev 3:12 PMobоитноtо може nаeLukas Kovalik 3-12 PMможе и ла брькамVacil Vaciley 242 pwewons uusSlockAcquired - Redis::set(self::POLLING LOCK KEY, ison encode(SlockData). "EX', self::LOCK TTL SECONDS. *NX*))значи пьрвото работиLukas Kovalik 313 PMVasil Vasiley 314 pvwe to ononns...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85252
|
2921
|
5
|
2026-05-28T12:14:57.267596+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970497267_m2.jpg...
|
Slack
|
Vasil Vasilev (DM) - Jiminny Inc - 3 new items - S Vasil Vasilev (DM) - Jiminny Inc - 3 new items - Slack...
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"bounds":{"left":0.5056516,"top":0.058260176,"width":0.011968086,"height":0.028731046},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"bounds":{"left":0.50299203,"top":0.10055866,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"bounds":{"left":0.50664896,"top":0.13806863,"width":0.009973404,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"bounds":{"left":0.50299203,"top":0.15482841,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":8,"bounds":{"left":0.50764626,"top":0.19233839,"width":0.007978723,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":6,"bounds":{"left":0.50299203,"top":0.20909816,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":8,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.012965426,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.0026595744,"height":0.011173184}},{"char_start":1,"char_count":7,"bounds":{"left":0.50764626,"top":0.24660814,"width":0.010638298,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":6,"bounds":{"left":0.50299203,"top":0.26336792,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":8,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0076462766,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5099734,"top":0.3008779,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Later","depth":6,"bounds":{"left":0.50299203,"top":0.31763768,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Later","depth":8,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.008643617,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5093085,"top":0.35514766,"width":0.0066489363,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"More…","depth":6,"bounds":{"left":0.50299203,"top":0.3719074,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"More","depth":8,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.008976064,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.0033244682,"height":0.011173184}},{"char_start":1,"char_count":3,"bounds":{"left":0.5106383,"top":0.4094174,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXStaticText","text":"Unreads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Threads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Huddles","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Drafts & sent","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Directories","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-backend-engineers","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-inner-team","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ai-chapter","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"alerts","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"backend","depth":15,"bounds":{"left":0.5422208,"top":0.09736632,"width":0.018284574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.09736632,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54521275,"top":0.09736632,"width":0.015292553,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"bugs","depth":15,"bounds":{"left":0.5422208,"top":0.11971269,"width":0.010638298,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.11971269,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":3,"bounds":{"left":0.54521275,"top":0.11971269,"width":0.00731383,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"confusion-clinic","depth":15,"bounds":{"left":0.5422208,"top":0.14205906,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.14205906,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54454786,"top":0.14205906,"width":0.032247342,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"donut_time","depth":15,"bounds":{"left":0.5422208,"top":0.16440542,"width":0.025265958,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.16440542,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54521275,"top":0.16440542,"width":0.022273935,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"engineering","depth":15,"bounds":{"left":0.5422208,"top":0.1867518,"width":0.025930852,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.1867518,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":10,"bounds":{"left":0.54488033,"top":0.1867518,"width":0.022938829,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"general","depth":15,"bounds":{"left":0.5422208,"top":0.20909816,"width":0.016289894,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.20909816,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54488033,"top":0.20909816,"width":0.013297873,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"happy_birthday","depth":15,"bounds":{"left":0.5422208,"top":0.23144454,"width":0.033909574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.23144454,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.54521275,"top":0.23144454,"width":0.030917553,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infosec_internal_all","depth":15,"bounds":{"left":0.5422208,"top":0.25379092,"width":0.041888297,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.25379092,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":19,"bounds":{"left":0.54355055,"top":0.25379092,"width":0.040226065,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infra-changes","depth":15,"bounds":{"left":0.5422208,"top":0.27613726,"width":0.029587766,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.27613726,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54355055,"top":0.27613726,"width":0.02825798,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infrastructure_dev","depth":15,"bounds":{"left":0.5422208,"top":0.29848364,"width":0.040226065,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.29848364,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":17,"bounds":{"left":0.54355055,"top":0.29848364,"width":0.038896278,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"jbu-team-info","depth":15,"bounds":{"left":0.5422208,"top":0.32083002,"width":0.029920213,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.32083002,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54355055,"top":0.32083002,"width":0.028590426,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"jiminny-bg","depth":15,"bounds":{"left":0.5422208,"top":0.34317636,"width":0.023271276,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.34317636,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54355055,"top":0.34317636,"width":0.021609042,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"platform-team","depth":15,"bounds":{"left":0.5422208,"top":0.36552274,"width":0.03158245,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.36552274,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54521275,"top":0.36552274,"width":0.028590426,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"platform-tickets","depth":15,"bounds":{"left":0.5422208,"top":0.38786912,"width":0.034906916,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.38786912,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54521275,"top":0.38786912,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"product_launches","depth":15,"bounds":{"left":0.5422208,"top":0.4102155,"width":0.03856383,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.4102155,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54521275,"top":0.4102155,"width":0.03557181,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"random","depth":15,"bounds":{"left":0.5422208,"top":0.43256184,"width":0.016954787,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.43256184,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":5,"bounds":{"left":0.54421544,"top":0.43256184,"width":0.014960106,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"releases","depth":15,"bounds":{"left":0.5422208,"top":0.45490822,"width":0.018284574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.45490822,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":7,"bounds":{"left":0.54421544,"top":0.45490822,"width":0.016289894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"support","depth":15,"bounds":{"left":0.5422208,"top":0.4772546,"width":0.017287234,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.4772546,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54454786,"top":0.4772546,"width":0.01462766,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"thank-yous","depth":15,"bounds":{"left":0.5422208,"top":0.49960095,"width":0.024601065,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.49960095,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54421544,"top":0.49960095,"width":0.022606382,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"the_people_of_jiminny","depth":15,"bounds":{"left":0.5422208,"top":0.5219473,"width":0.045212764,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5219473,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":20,"bounds":{"left":0.54421544,"top":0.5219473,"width":0.04720745,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Vasil Vasilev","depth":15,"bounds":{"left":0.5422208,"top":0.5746209,"width":0.026595745,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5746209,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54521275,"top":0.5746209,"width":0.023271276,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Stefka Stoyanova","depth":15,"bounds":{"left":0.5422208,"top":0.5969673,"width":0.037898935,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5969673,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54488033,"top":0.5969673,"width":0.03523936,"height":0.014365523}}],"role_description":"text"}]...
|
6359193766340236990
|
-5801313908412924186
|
idle
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
rapstomViewCoocWindowFV faVsco.|s ~#12121 on JY-20963-fx-Proinet vwnapers.oh© VoiceConsentPrefix.phpNotificationsv Observers© AccountObserver.phpCyActwwooserver.pnp© ContactObserver.phgGroupObserver.pho© LeadObserver.phoC ProfileObserver.phpC SocialAccountObserver.phg© UserObserver.pho© UserRoleObserver.phc> (i PoliciesuProvider• Queuea Reoositonea RulesaServicesDa ActivityAiReodrleallendarConnerimermobiacte@ DecorateActivityDummym Helnarsv D Hubspor(i) AccountSyncStrategyIhctiontMcontndSuncstrateon• D DTO› FieldsThtauendTNMAAAatOLekоkyseiwico.on© Kernel.phgMWiaKorCass wochexeR82183Opportunivsvncstratcov- Pac nation-ProsoecSearchStratco→- RedisService traits• Utils- Wechookc) Batchsunceo ector cho© BatchSvncRedsService.oCleantono@ GiosedDealStanpsSeniceclnaalise rccarica ono* Breturn T The result of the APi callprivate function executeRequest(callable SapiCall)ScacheKey = Sthis->getRateLimitCacheKeyOScacheotxozresac = keozst.oet scachekey)*if (is_string(ScachedExpiresAt) && is_numeric(ScachedExpiresAt)) 1Sremaining = naxl va(cint)) ScachedExpiresAt - tineon:hrow new kaceLinzcexceoe.onsrenaining,neruonSantwaittecarch leinronabieoi4 (Sthiso>isHubsootRateLinit(Se))thisosparse?erny.er e// NX: only the first job to receive a 429 in this burst sets the key.// Subsequent 42%s in the same burst leave the TTL untouched so theIl window is not reset by every concurrent job hitting the linit.Redis::set(ScacheKey, (string) (tine() + SretryAfter).Sthis->log->warning( Hubspot) Received 429 from API'.iteanSdl'configid'= Sthis->config->getido.ns Scetryatter-ENAeMAONNATthrow new RateLinitException message: "Hubspot returned 429'. SretryAfter. Se):Throw Senprivate function getRateLinitCachekevO: strinol...;TextRelayServiceTesto Inu co woy 1o:14.0+0.Setm onwatoes noesld console (PROD) x C Service.php# console fiaumA console [STAGING)D6.00€ANo a-created at > DAT: SUBCNOWOL IINTERVAL 3E DAYIIGROUP BY v.id, v.email, u.nane, u.softphone_numberORDER RY sns countDo jminny v795704FREIEE714-215716045 A1 A41 У 66 Aselect + Eron teans whenp dm15C3IEACONCAT(u.1d, CASE WHEN u.id = t.ouner id THEN " ouner' ELSE ** END) AS usen idt.ouner id FROM social accounts saJOIN users u on u.id = sa.sociable icJOIN teans t1.n<->1: on t.id = u.team_idNHERE u.tean_id = 1117 and sa.provider = *hubspot"SaLaeT * FRON accvaes whEkE uuzdcO b10 [CREDIT_CARD]-[CREDIT_CARD] = UU1d: # 79953459 Y28Cachado Codo XoKick of a new proisct. Make chunoe729E732- 735• JOIN activities a ON fd.activity_id = a.1dWHERE activity_id = 79933459• AND f.crn_provider_id = 'hs_activity_type';MARAt"GAAR NANGURASNS WhNA NONn SA TM CRARO18688) and created at > '2026-85-22' order by id descid IN ((18688. 13934. 7160):PARAtT GAAR MANGURAANOSid = 7168 order by id desc Linit 10:select * fron teans where id = 1117select * fron activity searches where user_1d = 31954:Pohettendactivity search_filters where actiivity_search_id TN (88882. 88992)c. Fix Texikelay service TesteC Multi-Picklist Layout DisplaNtietnheetdor10"PodswiothAr ianousoae lell minutas aaoIMY"E53mytwodturTaselkeThto%*4 space...
|
85249
|
NULL
|
NULL
|
NULL
|
|
85251
|
2920
|
5
|
2026-05-28T12:14:56.617722+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970496617_m1.jpg...
|
PhpStorm
|
faVsco.js – Client.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
#12121 on JY-20963-fix-im Project: faVsco.js, menu
#12121 on JY-20963-fix-import-on-deleted-entity, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
2
69
3
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Hubspot;
use HubSpot\Client\Crm\Deals\ApiException as DealApiException;
use HubSpot\Client\Crm\Contacts\ApiException as ContactApiException;
use HubSpot\Client\Crm\Companies\ApiException as CompanyApiException;
use HubSpot\Client\Crm\Contacts\Model\SimplePublicObjectWithAssociations as ContactsWithAssociations;
use HubSpot\Client\Crm\Companies\Model\SimplePublicObjectWithAssociations as CompaniesWithAssociations;
use HubSpot\Client\Crm\Deals\Model\SimplePublicObjectWithAssociations as DealWithAssociations;
use HubSpot\Client\Crm\Objects\Model\SimplePublicObjectInput;
use HubSpot\Client\Crm\Objects\Model\SimplePublicObjectWithAssociations as ObjectWithAssociations;
use HubSpot\Client\Crm\Pipelines\Model\Error;
use HubSpot\Client\Crm\Pipelines\Model\PipelineStage;
use HubSpot\Client\Crm\Properties\Model\Property;
use HubSpot\Discovery\Discovery;
use Jiminny\Exceptions\CrmException;
use Jiminny\Exceptions\RateLimitException;
use Jiminny\Exceptions\SocialAccountTokenInvalidException;
use Jiminny\Jobs\Crm\NoteObject;
use Jiminny\Models\Crm\Field;
use Jiminny\Services\Crm\BaseClient;
use Jiminny\Services\Crm\Hubspot\DTO\Response\Owner;
use Jiminny\Services\SocialAccountService;
use SevenShores\Hubspot\Exceptions\BadRequest;
use SevenShores\Hubspot\Exceptions\HubspotException;
use SevenShores\Hubspot\Factory;
use SevenShores\Hubspot\Http\Response;
use Jiminny\Services\Crm\Hubspot\Pagination\HubspotPaginationService;
use Illuminate\Support\Facades\Redis;
use Throwable;
/**
* @phpstan-type CrmFieldOption array{id:string, label:string, value?:string}
*/
class Client extends BaseClient implements HubspotClientInterface
{
public const string MIN_API_VERSION = '2';
public const string BASE_URL = '[URL_WITH_CREDENTIALS] T
*
* @param callable(): T $apiCall The API call to execute
*
* @throws RateLimitException When rate limit is hit or cached rate limit is active
*
* @return T The result of the API call
*/
private function executeRequest(callable $apiCall)
{
$cacheKey = $this->getRateLimitCacheKey();
$cachedExpiresAt = Redis::get($cacheKey);
if (is_string($cachedExpiresAt) && is_numeric($cachedExpiresAt)) {
$remaining = max(1, (int) $cachedExpiresAt - time());
throw new RateLimitException(
'Hubspot rate limit (cached circuit-breaker)',
$remaining,
);
}
try {
return $apiCall();
} catch (Throwable $e) {
if ($this->isHubspotRateLimit($e)) {
$retryAfter = $this->parseRetryAfter($e);
// NX: only the first job to receive a 429 in this burst sets the key.
// Subsequent 429s in the same burst leave the TTL untouched so the
// window is not reset by every concurrent job hitting the limit.
Redis::set($cacheKey, (string) (time() + $retryAfter), 'EX', $retryAfter, 'NX');
$this->log->warning('[Hubspot] Received 429 from API', [
'team_id' => $this->config->team_id,
'config_id' => $this->config->getId(),
'retry_after' => $retryAfter,
'reason' => $e->getMessage(),
]);
throw new RateLimitException('Hubspot returned 429', $retryAfter, $e);
}
throw $e;
}
}
private function getRateLimitCacheKey(): string
{
return sprintf('hubspot:ratelimit:config:%d', $this->config->getId());
}
private function isHubspotRateLimit(Throwable $e): bool
{
if ($e instanceof BadRequest
|| $e instanceof DealApiException
|| $e instanceof ContactApiException
|| $e instanceof CompanyApiException
|| $e instanceof \GuzzleHttp\Exception\RequestException
) {
return (int) $e->getCode() === 429;
}
return false;
}
private function parseRetryAfter(Throwable $e): int
{
if (method_exists($e, 'getResponseHeaders')) {
$headers = $e->getResponseHeaders() ?: [];
$value = $headers['Retry-After'] ?? $headers['retry-after'] ?? null;
if (is_array($value)) {
$value = $value[0] ?? null;
}
if (is_numeric($value)) {
return (int) $value;
}
}
$message = strtolower($e->getMessage());
if (str_contains($message, 'daily')) {
return 600;
}
if (str_contains($message, 'ten secondly')) {
return 10;
}
if (str_contains($message, 'secondly')) {
return 1;
}
$this->log->warning('[Hubspot] No retry-after header or known message, using default', [
'exception_class' => get_class($e),
'message' => $message,
]);
return 10;
}
public function getMinimumApiVersion(): string
{
return self::MIN_API_VERSION;
}
public function getInstance(): Factory
{
return new Factory([
'key' => $this->accessToken,
'oauth2' => true,
'base_url' => $this->baseUrl,
]);
}
public function getNewInstance(): Discovery
{
return \HubSpot\Factory::createWithAccessToken($this->accessToken);
}
/**
* Secondly and daily limits for Hubspot API
*
* Product Tier: Free & Starter | Professional & Enterprise | API add-on (any tier)
* Burst: 100/10 seconds | 150/10 seconds | 200/10 seconds
* Daily: 250,000 | 500,000 | 1,000,000
*
* Official documentation states: The search endpoints are rate limited to five requests per second.
* Since with 5 RPS were still hitting secondly rate limits we lowered it to 4
*/
public function getPaginatedData(array $payload, string $type, int $offset = 0): array
{
$total = 0;
$lastId = null;
$rows = [];
foreach ($this->getPaginatedDataGenerator($payload, $type, $offset, $total, $lastId) as $row) {
$rows[] = $row;
}
return ['results' => $rows, 'total' => $total, 'last_record' => $lastId];
}
/**
* @throws HubspotException
* @throws SocialAccountTokenInvalidException
* @throws BadRequest
*/
public function getPaginatedDataGenerator(
array $payload,
string $type,
int $offset = 0,
int &$total = 0,
?string &$lastRecordId = null
): \Generator {
return $this->paginationService->getPaginatedDataGenerator(
$this,
$payload,
$type,
$offset,
$total,
$lastRecordId
);
}
/**
* Execute a search request against HubSpot CRM objects with rate limiting.
*
* @param string $objectType The object type ('deals', 'companies', 'contacts', 'calls')
* @param array<string, mixed> $payload The search payload with filters, sorts, properties, etc.
*
* @throws RateLimitException When rate limit is hit
* @throws HubspotException On API errors
*
* @return array The search response with 'results', 'total', 'paging' keys
*/
public function search(string $objectType, array $payload): array
{
$endpoint = self::BASE_URL . "/crm/v3/objects/{$objectType}/search";
return $this->executeRequest(function () use ($endpoint, $payload) {
$response = $this->getInstance()->getClient()->request('POST', $endpoint, ['json' => $payload]);
return $response->toArray();
});
}
/**
* @throws DealApiException
* @throws CrmException
*/
public function getOpportunityById(string $crmId, array $fields): array
{
try {
$deal = $this->getNewInstance()->crm()->deals()->basicApi()->getById(
$crmId,
implode(',', $fields),
'companies,contacts'
);
} catch (DealApiException $e) {
$this->log->info('[Hubspot] Failed to fetch opportunity', [
'crm_id' => $crmId,
'reason' => $e->getMessage(),
]);
throw $e;
}
if (! $deal instanceof DealWithAssociations) {
throw new CrmException('Deal not found');
}
return [
'id' => $deal->getId(),
'properties' => $deal->getProperties(),
'associations' => $deal->getAssociations(),
];
}
/**
* Generic batch read method for HubSpot objects
*
* @param string $objectType The object type ('deals', 'companies', 'contacts')
* @param array<string> $crmIds Array of HubSpot object IDs (max 100)
* @param array<string> $fields Array of property names to fetch
*
* @return array<string, array> Array keyed by CRM ID with object data
*/
private function batchReadObjects(string $objectType, array $crmIds, array $fields): array
{
if (empty($crmIds)) {
return [];
}
$this->validateBatchSize($objectType, $crmIds);
$this->ensureValidToken();
try {
$batchConfig = $this->createBatchConfiguration($objectType);
$batchReadRequest = $this->prepareBatchRequest($batchConfig, $crmIds, $fields);
$response = $batchConfig['api']->read($batchReadRequest);
$this->validateApiResponse($response, $objectType);
$results = $this->processApiResults($response);
$this->logBatchResults($objectType, $crmIds, $results);
return $results;
} catch (\Throwable $e) {
$this->handleBatchError($e, $objectType, $crmIds);
}
}
private function validateBatchSize(string $objectType, array $crmIds): void
{
if (count($crmIds) > 100) {
throw new \InvalidArgumentException("Batch size cannot exceed 100 {$objectType}");
}
}
private function createBatchConfiguration(string $objectType): array
{
$configurations = [
'deals' => [
'batchReadRequest' => new \HubSpot\Client\Crm\Deals\Model\BatchReadInputSimplePublicObjectId(),
'inputClass' => \HubSpot\Client\Crm\Deals\Model\SimplePublicObjectId::class,
'api' => $this->getNewInstance()->crm()->deals()->batchApi(),
],
'companies' => [
'batchReadRequest' => new \HubSpot\Client\Crm\Companies\Model\BatchReadInputSimplePublicObjectId(),
'inputClass' => \HubSpot\Client\Crm\Companies\Model\SimplePublicObjectId::class,
'api' => $this->getNewInstance()->crm()->companies()->batchApi(),
],
'contacts' => [
'batchReadRequest' => new \HubSpot\Client\Crm\Contacts\Model\BatchReadInputSimplePublicObjectId(),
'inputClass' => \HubSpot\Client\Crm\Contacts\Model\SimplePublicObjectId::class,
'api' => $this->getNewInstance()->crm()->contacts()->batchApi(),
],
];
if (! isset($configurations[$objectType])) {
throw new \InvalidArgumentException("Unsupported object type: {$objectType}");
}
return $configurations[$objectType];
}
private function prepareBatchRequest(array $batchConfig, array $crmIds, array $fields): object
{
$batchReadRequest = $batchConfig['batchReadRequest'];
$inputClass = $batchConfig['inputClass'];
$inputs = array_map(function ($crmId) use ($inputClass) {
$input = new $inputClass();
$input->setId($crmId);
return $input;
}, $crmIds);
$batchReadRequest->setInputs($inputs);
$batchReadRequest->setProperties($fields);
return $batchReadRequest;
}
private function validateApiResponse($response, string $objectType): void
{
if (! $response) {
throw new CrmException("HubSpot API returned null response for {$objectType} batch read");
}
}
private function processApiResults($response): array
{
$results = [];
$responseResults = $response->getResults();
if ($responseResults) {
foreach ($responseResults as $object) {
if ($object && $object->getId()) {
$results[$object->getId()] = [
'id' => $object->getId(),
'properties' => $object->getProperties() ?: [],
];
}
}
}
return $results;
}
private function logBatchResults(string $objectType, array $crmIds, array $results): void
{
$this->log->info("[HubSpot] Batch fetched {$objectType}", [
'requested_count' => count($crmIds),
'returned_count' => count($results),
'crm_ids' => $crmIds,
]);
}
private function handleBatchError(\Throwable $e, string $objectType, array $crmIds): void
{
$errorMessage = $e->getMessage() ?: 'Unknown error';
$errorTrace = $e->getTraceAsString() ?: 'No trace available';
$this->log->error("[HubSpot] Failed to batch fetch {$objectType}", [
'crm_ids' => $crmIds,
'error' => $errorMessage,
'trace' => $errorTrace,
]);
throw new CrmException("Failed to batch fetch {$objectType}: " . $errorMessage);
}
/**
* Batch read multiple opportunities by their CRM IDs
*
* @param array<string> $crmIds Array of HubSpot deal IDs (max 100)
* @param array<string> $fields Array of property names to fetch
*
* @return array<string, array> Array keyed by CRM ID with opportunity data
*/
public function getOpportunitiesByIds(array $crmIds, array $fields): array
{
return $this->batchReadObjects('deals', $crmIds, $fields);
}
/**
* Batch read multiple companies by their CRM IDs
*
* @param array<string> $crmIds Array of HubSpot company IDs (max 100)
* @param array<string> $fields Array of property names to fetch
*
* @return array<string, array> Array keyed by CRM ID with company data
*/
public function getCompaniesByIds(array $crmIds, array $fields): array
{
return $this->batchReadObjects('companies', $crmIds, $fields);
}
/**
* Batch read multiple contacts by their CRM IDs
*
* @param array<string> $crmIds Array of HubSpot contact IDs (max 100)
* @param array<string> $fields Array of property names to fetch
*
* @return array<string, array> Array keyed by CRM ID with contact data
*/
public function getContactsByIds(array $crmIds, array $fields): array
{
return $this->batchReadObjects('contacts', $crmIds, $fields);
}
/**
* @throws CompanyApiException
* @throws CrmException
*/
public function getAccountById(string $crmId, array $fields): array
{
try {
$company = $this->getNewInstance()->crm()->companies()->basicApi()->getById(
$crmId,
implode(',', $fields),
);
} catch (CompanyApiException $e) {
$this->log->info('[Hubspot] Failed to fetch account', [
'crm_id' => $crmId,
'reason' => $e->getMessage(),
]);
throw $e;
}
if (! $company instanceof CompaniesWithAssociations) {
throw new CrmException('Account not found');
}
return [
'id' => $company->getId(),
'properties' => $company->getProperties(),
];
}
/**
* @throws ContactApiException
* @throws CrmException
*/
public function getContactById(string $crmId, array $fields): array
{
try {
$contact = $this->getNewInstance()->crm()->contacts()->basicApi()->getById(
$crmId,
implode(',', $fields)
);
} catch (ContactApiException $e) {
$this->log->info('[Hubspot] Failed to fetch contact', [
'crm_id' => $crmId,
'reason' => $e->getMessage(),
]);
throw $e;
}
if (! $contact instanceof ContactsWithAssociations) {
throw new CrmException('Contact not found');
}
return [
'id' => $contact->getId(),
'properties' => $contact->getProperties(),
];
}
/**
* This is email search request that Hubspot offers as GET (more generous quota)
*/
public function getContactByEmail(string $email, array $fields = []): array
{
try {
$contact = $this->getNewInstance()->crm()->contacts()->basicApi()->getById(
$email,
implode(',', $fields),
null,
false,
'email'
);
return [
'id' => $contact->getId(),
'properties' => $contact->getProperties(),
];
} catch (ContactApiException $e) {
$this->log->info('[Hubspot] Failed to fetch contact', [
'email' => $email,
'reason' => $e->getMessage(),
]);
return [];
}
}
/**
* @throws CrmException
*/
public function fetchProperty(string $objectType, string $propertyId): Property
{
$result = $this->getNewInstance()->crm()->properties()->coreApi()->getByName($objectType, $propertyId);
if (! $result instanceof Property) {
$this->log->error('[Hubspot] Failed to fetch property', [
'object_type' => $objectType,
'property_id' => $propertyId,
'reason' => $result->getMessage(),
]);
throw new CrmException('Failed to fetch property');
}
return $result;
}
/**
* @return array<CrmFieldOption>
*/
public function fetchPropertyOptions(string $objectType, string $propertyId): array
{
/** @var array<CrmFieldOption> */
return $this->fetchProperty($objectType, $propertyId)->getOptions();
}
/**
* @return array<array{id:string, label:string, deleted:bool}>
*/
public function fetchCallDispositions(): array
{
/** @var Response $response */
$response = $this->getInstance()->engagements()->getCallDispositions();
/**
* @var array<array{
* id:string,
* label:string,
* deleted: bool
* }>
*/
return $response->toArray();
}
/**
* @return array<CrmFieldOption>
*/
public function fetchOpportunityPipelineStages(): array
{
$stages = [];
$apiResponse = $this->getNewInstance()->crm()->pipelines()->pipelinesApi()->getAll('deals');
if ($apiResponse instanceof Error) {
$this->log->error('[Hubspot] Failed to fetch opportunity pipelines', [
'reason' => $apiResponse->getMessage(),
]);
return [];
}
foreach ($apiResponse->getResults() as $pipeline) {
$pipelineStages = array_map(
static function (PipelineStage $stage) {
return [
'id' => $stage->getId(),
'label' => $stage->getLabel(),
];
},
$pipeline->getStages()
);
$stages = array_merge($stages, $pipelineStages);
}
return $stages;
}
public function fetchOpportunityPipelines(): array
{
$pipelines = [];
try {
$apiResponse = $this->makeRequest('/crm/v3/pipelines/deals');
} catch (\Exception $e) {
$this->log->info('[Hubspot] Failed to fetch opportunity pipelines', [
'reason' => $e->getMessage(),
]);
return [];
}
$response = $apiResponse->toArray();
foreach ($response['results'] as $pipeline) {
$pipelines[] = [
'id' => $pipeline['id'],
'label' => $pipeline['label'],
];
}
return $pipelines;
}
/**
* @return array<CrmFieldOption>
*/
public function fetchMeetingOutcomeFieldOptions(Field $field): array
{
return $field->getCrmProviderId() === 'meetingOutcome'
? $this->fetchMeetingOutcomeTypes()
: $this->fetchCallActivityTypes();
}
public function fetchMeetingOutcomeTypes(): array
{
return $this->extractMeetingTypeOptions(
'[URL_WITH_CREDENTIALS] Response $response */
$response = $this->getInstance()
->getClient()
->request('GET', $endpoint);
/**
* @var array<array{
* value: string,
* label: string,
* displayOrder: int
* }> $optionData
*/
$optionData = $response->toArray()['options'] ?? [];
$options = [];
foreach ($optionData as $item) {
$options[] = [
'id' => $item['value'],
'value' => $item['value'],
'label' => $item['label'],
'display_order' => $item['displayOrder'],
];
}
return $options;
}
/**
* @return array<CrmFieldOption>
*/
public function fetchDispositionFieldOptions(): array
{
$options = [];
$dispositions = $this->fetchCallDispositions();
foreach ($dispositions as $disposition) {
if ($disposition['deleted'] !== false) {
continue;
}
$option['value'] = $disposition['id'];
$option['id'] = $disposition['id'];
$option['label'] = $disposition['label'];
$options[] = $option;
}
return $options;
}
/**
* @return array<CrmFieldOption>
*/
public function fetchOpportunityFieldOptions(Field $field): array
{
if ($field->isStageField()) {
return $this->fetchOpportunityPipelineStages();
}
if ($field->isPipelineField()) {
return $this->fetchOpportunityPipelines();
}
return $this->fetchPropertyOptions('deals', $field->getCrmProviderId());
}
/**
* @throws BadRequest
* @throws HubspotException
*/
public function makeRequest(string $endpoint, $method = 'GET', $payload = [], ?string $queryString = null)
{
$endpoint = self::BASE_URL . $endpoint;
if ($method === 'GET') {
return $this->getInstance()->getClient()?->request(
method: $method,
endpoint: $endpoint,
query_string: $queryString
);
} else {
return $this->getInstance()->getClient()->request($method, $endpoint, [
'json' => ($payload),
]);
}
}
/**
* @throws BadRequest
* @throws HubspotException
*/
public function createMeeting(array $payload): Response
{
$endpoint = '/crm/v3/objects/meetings';
return $this->makeRequest($endpoint, 'POST', $payload);
}
/**
* @throws BadRequest
* @throws HubspotException
*/
public function updateMeeting(string $meetingId, array $payload): Response
{
$endpoint = '/crm/v3/objects/meetings/' . $meetingId;
return $this->makeRequest($endpoint, 'PATCH', $payload);
}
/**
* @throws \Exception
*/
public function createNote(
string $body,
string $ownerId,
int $timestamp,
string $objectId,
NoteObject $noteObject
): ?string {
try {
$noteInput = new SimplePublicObjectInput([
'properties' => [
'hs_note_body' => $body,
'hubspot_owner_id' => $ownerId,
'hs_timestamp' => $timestamp,
],
]);
// Create note
$note = $this->getNewInstance()->crm()->objects()->basicApi()->create('note', $noteInput);
$this->getNewInstance()->crm()->objects()->associationsApi()->create(
'note',
$note->getId(),
$this->getNoteObject($noteObject),
$objectId,
$this->getNoteAssociationType($noteObject),
);
return $note->getId();
} catch (\Exception $e) {
$this->log->error('[Hubspot] Failed to create note', [
'objectId' => $objectId,
'noteObject' => $noteObject->getObjectType(),
'reason' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return null;
}
public function updateEngagement(string $objectId, array $engagement, array $metadata): void
{
$this->getInstance()->engagements()->update($objectId, $engagement, $metadata);
}
public function getEngagementData(string $engagementId): array
{
$engagement = $this->getInstance()->engagements()->get($engagementId);
return $engagement->toArray();
}
public function createEngagement(array $engagement, array $associations, array $metadata): Response
{
return $this->getInstance()
->engagements()
->create($engagement, $associations, $metadata);
}
public function isUnauthorizedException(\Exception $e): bool
{
// Check for specific HubSpot API exception types first
if ($e instanceof BadRequest) {
// BadRequest can contain 401 status codes
return $e->getCode() === 401;
}
// Check for HTTP client exceptions with status codes
if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
$response = $e->getResponse();
if ($response !== null) {
return $response->getStatusCode() === 401;
}
}
// Check for Guzzle HTTP exceptions
if ($e instanceof \GuzzleHttp\Exception\ClientException) {
return $e->getCode() === 401;
}
// Fallback to string matching as last resort, but be more specific
$message = strtolower($e->getMessage());
return str_contains($message, '401 unauthorized') ||
str_contains($message, 'http 401') ||
str_contains($message, 'status code 401') ||
(preg_match('/\b401\b/', $message) && str_contains($message, 'unauthorized'));
}
/**
* Validates and refreshes the access token if needed before API requests.
* This ensures long-running processes don't fail due to token expiration.
*
* @throws SocialAccountTokenInvalidException
*/
public function ensureValidToken(): void
{
if ($this->oauthAccount === null) {
return;
}
$newToken = $this->tokenManager->ensureValidToken($this->oauthAccount);
if ($newToken !== null) {
$this->accessToken = $newToken;
}
}
public function getConfig()
{
return $this->config;
}
// returns only active (archived=false)
public function getOwners(): array
{
return $this->getNewInstance()->crm()->owners()->getAll();
}
/**
* @param bool $archived
*
* @return array<Owner>|[]
*/
public function getOwnersArchived(bool $archived = true): array
{
$endpoint = '/crm/v3/owners';
$queryParams = [
'archived' => $archived ? 'true' : 'false',
];
$queryString = http_build_query($queryParams);
$owners = [];
try {
$response = $this->makeRequest(endpoint: $endpoint, queryString: $queryString);
$responseData = $response?->toArray();
foreach ($responseData['results'] as $result) {
try {
$owners[] = Owner::create($result);
} catch (Throwable $e) {
$this->log->error('[HubSpot] Failed to process owner data', [
'result' => $result,
'error' => $e->getMessage(),
]);
continue;
}
}
} catch (Throwable $e) {
$this->log->error('HubSpot] Failed to fetch owners', [
'archived' => $archived,
'error' => $e->getMessage(),
]);
return [];
}
return $owners;
}
public function getMeeting(string $engagementId): ObjectWithAssociations
{
return $this->getNewInstance()->crm()->objects()->basicApi()
->getById('meeting', $engagementId, null, 'contact,company,deal');
}
public function deleteEngagement(string $engagementId): void
{
$this->getInstance()->engagements()->delete((int) $engagementId);
}
public function getAssociationsData(array $ids, string $fromObject, string $toObject): array
{
$associationData = [];
$idChunks = array_chunk($ids, self::ASSOCIATIONS_BATCH_SIZE_LIMIT);
foreach ($idChunks as $idChunk) {
try {
$batchInput = new \HubSpot\Client\Crm\Associations\Model\BatchInputPublicObjectId();
$batchInput->setInputs(array_map(function ($id) {
$publicObjectId = new \HubSpot\Client\Crm\Associations\Model\PublicObjectId();
$publicObjectId->setId($id);
return $publicObjectId;
}, $idChunk));
$associatedObjectsData = $this
->getNewInstance()
->crm()
->associations()
->batchApi()
->read($fromObject, $toObject, $batchInput);
if ($associatedObjectsData instanceof \HubSpot\Client\Crm\Associations\Model\BatchResponsePublicAssociationMulti) {
foreach ($associatedObjectsData->getResults() as $association) {
$from = $association->getFrom()->getId();
$toAssociations = $association->getTo();
if (! empty($toAssociations)) {
$associationData[$from] = array_map(function ($item) {
return $item->getId();
}, $toAssociations);
}
}
}
} catch (\Exception $e) {
$this->log->error('[Hubspot] Failed to fetch associations', [
'from_object' => $fromObject,
'to_object' => $toObject,
'reason' => $e->getMessage(),
]);
}
}
return $associationData;
}
/**
* @throws \Exception
*/
private function getNoteAssociationType(NoteObject $noteObject): string
{
return match($noteObject) {
NoteObject::Opportunity => 'note_to_deal',
NoteObject::Lead, NoteObject::Contact => 'note_to_contact', // or 'note_to_lead' if your portal supports it
NoteObject::Account => 'note_to_company',
NoteObject::Call, NoteObject::Event => throw new \Exception('Not supported'),
};
}
/**
* @throws \Exception
*/
private function getNoteObject(NoteObject $noteObject): string
{
return match($noteObject) {
NoteObject::Opportunity => 'deal',
NoteObject::Lead, NoteObject::Contact => 'contact',
NoteObject::Account => 'company',
NoteObject::Call, NoteObject::Event => throw new \Exception('Not supported'),
};
}
public function addAssociations(string $objectType, string $associationType, array $payload): Response
{
$endpoint = "/crm/v4/associations/$objectType/$associationType/batch/create";
return $this->makeRequest($endpoint, 'POST', $payload);
}
public function removeAssociations(string $objectType, string $associationType, array $payload): Response
{
$endpoint = "/crm/v4/associations/$objectType/$associationType/batch/archive";
return $this->makeRequest($endpoint, 'POST', $payload);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
45
1
41
66
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993
SELECT * FROM users WHERE id = 25061;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 994;
SELECT * FROM crm_profiles WHERE user_id = 25061;
select * from crm_configurations where id = 834;
SELECT * FROM teams WHERE id = 882;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;
SELECT * FROM contacts where crm_configuration_id = 834;
SELECT * FROM opportunities WHERE team_id = 933
# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');
AND id IN (8482561,18352941,19042734,19232139,19445140,19472541);
SELECT * FROM opportunity_contacts
WHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 485; #
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
select crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id
where crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')
# and l.converted_at IS NOT NULL
;
# [PASSWORD_DOTS]
SELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')
and opportunity_id IS NULL
order by id desc;
SELECT * FROM teams WHERE id = 604; # 598
SELECT * FROM activities WHERE id = 74410828; # [EMAIL]
SELECT * FROM accounts WHERE id = 20068382;
SELECT * FROM accounts WHERE id = 35186038;
SELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 559 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;
select * from sidekick_settings where team_id = 781;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100
SELECT * FROM crm_layouts WHERE crm_configuration_id = 711;
SELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL
and is_internal = 0 and status = 'completed'
order by id desc;
SELECT * FROM crm_layout_entities
WHERE crm_layout_id IN (2352, 2353);
;
SELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 556 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;
SELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;
select * from contacts
where crm_configuration_id = 530
and crm_provider_id = 872252;
select * from activities where crm_configuration_id = 530
and user_id = 14343 and type like '%softphone%'
and created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);
SELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t
JOIN crm_configurations c ON t.id = c.team_id
WHERE t.status = 'active';
SELECT * FROM teams where id = 1091;
SELECT * FROM crm_configurations where team_id = 1091;
SELECT * FROM activity_providers where team_id = 1091;
SELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT * FROM teams WHERE name LIKE '%Leadventure%';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1091 and sa.provider = 'salesforce';
SELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812
SELECT * FROM teams where id = 862;
SELECT * FROM crm_configurations where team_id = 862;
SELECT * FROM activity_providers where team_id = 862;
SELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT t.id, crm.id, crm.provider, ap.* FROM teams t
join crm_configurations crm on t.id = crm.team_id
join activity_providers ap on t.id = ap.team_id
where t.status = 'active' and ap.is_enabled = 1
and crm.provider = 'hubspot'
and ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',
'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');
SELECT * FROM teams where id = 1068;
SELECT * FROM crm_configurations where team_id = 1068;
SELECT * FROM activity_providers where team_id = 1068;
SELECT * FROM activities a
where crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')
and a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'
)
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by a.id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1068 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262
SELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
select * from crm_layouts where crm_configuration_id = 834;
select * from crm_layout_entities where crm_layout_id = 2780;
select * from crm_fields where id IN (321153,321192,321193,321194);
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1057 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8
SELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20
SELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10
SELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #
SELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;
select * from users where team_id = 51; # 7783
SELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130
select * from activity_searches where user_id = 7783;
select * from activity_search_filters where activity_search_id IN (32291, 32292);
SELECT asf.activity_search_id, asf.id, asf.value
FROM activity_search_filters asf
WHERE asf.filter = 'group_id'
AND asf.value IN (
SELECT CONCAT(
HEX(SUBSTR(uuid, 5, 4)), '-',
HEX(SUBSTR(uuid, 3, 2)), '-',
HEX(SUBSTR(uuid, 1, 2)), '-',
HEX(SUBSTR(uuid, 9, 2)), '-',
HEX(SUBSTR(uuid, 11))
)
FROM groups
WHERE deleted_at ...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12121 on JY-20963-fix-import-on-deleted-entity, menu","depth":5,"on_screen":true,"help_text":"Pull request #12121 exists for current branch JY-20963-fix-import-on-deleted-entity","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"69","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"3","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Hubspot;\n\nuse HubSpot\\Client\\Crm\\Deals\\ApiException as DealApiException;\nuse HubSpot\\Client\\Crm\\Contacts\\ApiException as ContactApiException;\nuse HubSpot\\Client\\Crm\\Companies\\ApiException as CompanyApiException;\nuse HubSpot\\Client\\Crm\\Contacts\\Model\\SimplePublicObjectWithAssociations as ContactsWithAssociations;\nuse HubSpot\\Client\\Crm\\Companies\\Model\\SimplePublicObjectWithAssociations as CompaniesWithAssociations;\nuse HubSpot\\Client\\Crm\\Deals\\Model\\SimplePublicObjectWithAssociations as DealWithAssociations;\nuse HubSpot\\Client\\Crm\\Objects\\Model\\SimplePublicObjectInput;\nuse HubSpot\\Client\\Crm\\Objects\\Model\\SimplePublicObjectWithAssociations as ObjectWithAssociations;\nuse HubSpot\\Client\\Crm\\Pipelines\\Model\\Error;\nuse HubSpot\\Client\\Crm\\Pipelines\\Model\\PipelineStage;\nuse HubSpot\\Client\\Crm\\Properties\\Model\\Property;\nuse HubSpot\\Discovery\\Discovery;\nuse Jiminny\\Exceptions\\CrmException;\nuse Jiminny\\Exceptions\\RateLimitException;\nuse Jiminny\\Exceptions\\SocialAccountTokenInvalidException;\nuse Jiminny\\Jobs\\Crm\\NoteObject;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Services\\Crm\\BaseClient;\nuse Jiminny\\Services\\Crm\\Hubspot\\DTO\\Response\\Owner;\nuse Jiminny\\Services\\SocialAccountService;\nuse SevenShores\\Hubspot\\Exceptions\\BadRequest;\nuse SevenShores\\Hubspot\\Exceptions\\HubspotException;\nuse SevenShores\\Hubspot\\Factory;\nuse SevenShores\\Hubspot\\Http\\Response;\nuse Jiminny\\Services\\Crm\\Hubspot\\Pagination\\HubspotPaginationService;\nuse Illuminate\\Support\\Facades\\Redis;\nuse Throwable;\n\n/**\n * @phpstan-type CrmFieldOption array{id:string, label:string, value?:string}\n */\nclass Client extends BaseClient implements HubspotClientInterface\n{\n public const string MIN_API_VERSION = '2';\n\n public const string BASE_URL = 'https://api.hubapi.com';\n\n public const int ASSOCIATIONS_BATCH_SIZE_LIMIT = 1000;\n\n private HubspotPaginationService $paginationService;\n private HubspotTokenManager $tokenManager;\n\n public function __construct(\n SocialAccountService $socialAccountService,\n HubspotPaginationService $paginationService,\n HubspotTokenManager $tokenManager\n ) {\n parent::__construct($socialAccountService);\n $this->paginationService = $paginationService;\n $this->tokenManager = $tokenManager;\n\n $this->setBaseUrl(self::BASE_URL);\n $this->setVersion(self::MIN_API_VERSION);\n }\n\n /**\n * Execute a HubSpot API call with rate limit handling.\n *\n * On a 429, stores the absolute expiry timestamp with SET NX (first writer wins).\n * This means all subsequent jobs that also receive 429 in the same burst do not\n * reset the TTL — the window is anchored to the first 429, not the last.\n * Readers compute the remaining wait from the stored timestamp, so jobs that check\n * the cache near expiry are not delayed longer than necessary.\n *\n * @template T\n *\n * @param callable(): T $apiCall The API call to execute\n *\n * @throws RateLimitException When rate limit is hit or cached rate limit is active\n *\n * @return T The result of the API call\n */\n private function executeRequest(callable $apiCall)\n {\n $cacheKey = $this->getRateLimitCacheKey();\n\n $cachedExpiresAt = Redis::get($cacheKey);\n if (is_string($cachedExpiresAt) && is_numeric($cachedExpiresAt)) {\n $remaining = max(1, (int) $cachedExpiresAt - time());\n\n throw new RateLimitException(\n 'Hubspot rate limit (cached circuit-breaker)',\n $remaining,\n );\n }\n\n try {\n return $apiCall();\n } catch (Throwable $e) {\n if ($this->isHubspotRateLimit($e)) {\n $retryAfter = $this->parseRetryAfter($e);\n\n // NX: only the first job to receive a 429 in this burst sets the key.\n // Subsequent 429s in the same burst leave the TTL untouched so the\n // window is not reset by every concurrent job hitting the limit.\n Redis::set($cacheKey, (string) (time() + $retryAfter), 'EX', $retryAfter, 'NX');\n\n $this->log->warning('[Hubspot] Received 429 from API', [\n 'team_id' => $this->config->team_id,\n 'config_id' => $this->config->getId(),\n 'retry_after' => $retryAfter,\n 'reason' => $e->getMessage(),\n ]);\n\n throw new RateLimitException('Hubspot returned 429', $retryAfter, $e);\n }\n\n throw $e;\n }\n }\n\n private function getRateLimitCacheKey(): string\n {\n return sprintf('hubspot:ratelimit:config:%d', $this->config->getId());\n }\n\n private function isHubspotRateLimit(Throwable $e): bool\n {\n if ($e instanceof BadRequest\n || $e instanceof DealApiException\n || $e instanceof ContactApiException\n || $e instanceof CompanyApiException\n || $e instanceof \\GuzzleHttp\\Exception\\RequestException\n ) {\n return (int) $e->getCode() === 429;\n }\n\n return false;\n }\n\n private function parseRetryAfter(Throwable $e): int\n {\n if (method_exists($e, 'getResponseHeaders')) {\n $headers = $e->getResponseHeaders() ?: [];\n $value = $headers['Retry-After'] ?? $headers['retry-after'] ?? null;\n if (is_array($value)) {\n $value = $value[0] ?? null;\n }\n if (is_numeric($value)) {\n return (int) $value;\n }\n }\n\n $message = strtolower($e->getMessage());\n\n if (str_contains($message, 'daily')) {\n return 600;\n }\n if (str_contains($message, 'ten secondly')) {\n return 10;\n }\n if (str_contains($message, 'secondly')) {\n return 1;\n }\n\n $this->log->warning('[Hubspot] No retry-after header or known message, using default', [\n 'exception_class' => get_class($e),\n 'message' => $message,\n ]);\n\n return 10;\n }\n\n public function getMinimumApiVersion(): string\n {\n return self::MIN_API_VERSION;\n }\n\n public function getInstance(): Factory\n {\n return new Factory([\n 'key' => $this->accessToken,\n 'oauth2' => true,\n 'base_url' => $this->baseUrl,\n ]);\n }\n\n public function getNewInstance(): Discovery\n {\n return \\HubSpot\\Factory::createWithAccessToken($this->accessToken);\n }\n\n /**\n * Secondly and daily limits for Hubspot API\n *\n * Product Tier: Free & Starter | Professional & Enterprise | API add-on (any tier)\n * Burst: 100/10 seconds | 150/10 seconds | 200/10 seconds\n * Daily: 250,000 | 500,000 | 1,000,000\n *\n * Official documentation states: The search endpoints are rate limited to five requests per second.\n * Since with 5 RPS were still hitting secondly rate limits we lowered it to 4\n */\n public function getPaginatedData(array $payload, string $type, int $offset = 0): array\n {\n $total = 0;\n $lastId = null;\n $rows = [];\n foreach ($this->getPaginatedDataGenerator($payload, $type, $offset, $total, $lastId) as $row) {\n $rows[] = $row;\n }\n\n return ['results' => $rows, 'total' => $total, 'last_record' => $lastId];\n }\n\n /**\n * @throws HubspotException\n * @throws SocialAccountTokenInvalidException\n * @throws BadRequest\n */\n public function getPaginatedDataGenerator(\n array $payload,\n string $type,\n int $offset = 0,\n int &$total = 0,\n ?string &$lastRecordId = null\n ): \\Generator {\n return $this->paginationService->getPaginatedDataGenerator(\n $this,\n $payload,\n $type,\n $offset,\n $total,\n $lastRecordId\n );\n }\n\n /**\n * Execute a search request against HubSpot CRM objects with rate limiting.\n *\n * @param string $objectType The object type ('deals', 'companies', 'contacts', 'calls')\n * @param array<string, mixed> $payload The search payload with filters, sorts, properties, etc.\n *\n * @throws RateLimitException When rate limit is hit\n * @throws HubspotException On API errors\n *\n * @return array The search response with 'results', 'total', 'paging' keys\n */\n public function search(string $objectType, array $payload): array\n {\n $endpoint = self::BASE_URL . \"/crm/v3/objects/{$objectType}/search\";\n\n return $this->executeRequest(function () use ($endpoint, $payload) {\n $response = $this->getInstance()->getClient()->request('POST', $endpoint, ['json' => $payload]);\n\n return $response->toArray();\n });\n }\n\n /**\n * @throws DealApiException\n * @throws CrmException\n */\n public function getOpportunityById(string $crmId, array $fields): array\n {\n try {\n $deal = $this->getNewInstance()->crm()->deals()->basicApi()->getById(\n $crmId,\n implode(',', $fields),\n 'companies,contacts'\n );\n } catch (DealApiException $e) {\n $this->log->info('[Hubspot] Failed to fetch opportunity', [\n 'crm_id' => $crmId,\n 'reason' => $e->getMessage(),\n ]);\n\n throw $e;\n }\n\n if (! $deal instanceof DealWithAssociations) {\n throw new CrmException('Deal not found');\n }\n\n return [\n 'id' => $deal->getId(),\n 'properties' => $deal->getProperties(),\n 'associations' => $deal->getAssociations(),\n ];\n }\n\n /**\n * Generic batch read method for HubSpot objects\n *\n * @param string $objectType The object type ('deals', 'companies', 'contacts')\n * @param array<string> $crmIds Array of HubSpot object IDs (max 100)\n * @param array<string> $fields Array of property names to fetch\n *\n * @return array<string, array> Array keyed by CRM ID with object data\n */\n private function batchReadObjects(string $objectType, array $crmIds, array $fields): array\n {\n if (empty($crmIds)) {\n return [];\n }\n\n $this->validateBatchSize($objectType, $crmIds);\n $this->ensureValidToken();\n\n try {\n $batchConfig = $this->createBatchConfiguration($objectType);\n $batchReadRequest = $this->prepareBatchRequest($batchConfig, $crmIds, $fields);\n $response = $batchConfig['api']->read($batchReadRequest);\n\n $this->validateApiResponse($response, $objectType);\n\n $results = $this->processApiResults($response);\n $this->logBatchResults($objectType, $crmIds, $results);\n\n return $results;\n } catch (\\Throwable $e) {\n $this->handleBatchError($e, $objectType, $crmIds);\n }\n }\n\n private function validateBatchSize(string $objectType, array $crmIds): void\n {\n if (count($crmIds) > 100) {\n throw new \\InvalidArgumentException(\"Batch size cannot exceed 100 {$objectType}\");\n }\n }\n\n private function createBatchConfiguration(string $objectType): array\n {\n $configurations = [\n 'deals' => [\n 'batchReadRequest' => new \\HubSpot\\Client\\Crm\\Deals\\Model\\BatchReadInputSimplePublicObjectId(),\n 'inputClass' => \\HubSpot\\Client\\Crm\\Deals\\Model\\SimplePublicObjectId::class,\n 'api' => $this->getNewInstance()->crm()->deals()->batchApi(),\n ],\n 'companies' => [\n 'batchReadRequest' => new \\HubSpot\\Client\\Crm\\Companies\\Model\\BatchReadInputSimplePublicObjectId(),\n 'inputClass' => \\HubSpot\\Client\\Crm\\Companies\\Model\\SimplePublicObjectId::class,\n 'api' => $this->getNewInstance()->crm()->companies()->batchApi(),\n ],\n 'contacts' => [\n 'batchReadRequest' => new \\HubSpot\\Client\\Crm\\Contacts\\Model\\BatchReadInputSimplePublicObjectId(),\n 'inputClass' => \\HubSpot\\Client\\Crm\\Contacts\\Model\\SimplePublicObjectId::class,\n 'api' => $this->getNewInstance()->crm()->contacts()->batchApi(),\n ],\n ];\n\n if (! isset($configurations[$objectType])) {\n throw new \\InvalidArgumentException(\"Unsupported object type: {$objectType}\");\n }\n\n return $configurations[$objectType];\n }\n\n private function prepareBatchRequest(array $batchConfig, array $crmIds, array $fields): object\n {\n $batchReadRequest = $batchConfig['batchReadRequest'];\n $inputClass = $batchConfig['inputClass'];\n\n $inputs = array_map(function ($crmId) use ($inputClass) {\n $input = new $inputClass();\n $input->setId($crmId);\n\n return $input;\n }, $crmIds);\n\n $batchReadRequest->setInputs($inputs);\n $batchReadRequest->setProperties($fields);\n\n return $batchReadRequest;\n }\n\n private function validateApiResponse($response, string $objectType): void\n {\n if (! $response) {\n throw new CrmException(\"HubSpot API returned null response for {$objectType} batch read\");\n }\n }\n\n private function processApiResults($response): array\n {\n $results = [];\n $responseResults = $response->getResults();\n\n if ($responseResults) {\n foreach ($responseResults as $object) {\n if ($object && $object->getId()) {\n $results[$object->getId()] = [\n 'id' => $object->getId(),\n 'properties' => $object->getProperties() ?: [],\n ];\n }\n }\n }\n\n return $results;\n }\n\n private function logBatchResults(string $objectType, array $crmIds, array $results): void\n {\n $this->log->info(\"[HubSpot] Batch fetched {$objectType}\", [\n 'requested_count' => count($crmIds),\n 'returned_count' => count($results),\n 'crm_ids' => $crmIds,\n ]);\n }\n\n private function handleBatchError(\\Throwable $e, string $objectType, array $crmIds): void\n {\n $errorMessage = $e->getMessage() ?: 'Unknown error';\n $errorTrace = $e->getTraceAsString() ?: 'No trace available';\n\n $this->log->error(\"[HubSpot] Failed to batch fetch {$objectType}\", [\n 'crm_ids' => $crmIds,\n 'error' => $errorMessage,\n 'trace' => $errorTrace,\n ]);\n\n throw new CrmException(\"Failed to batch fetch {$objectType}: \" . $errorMessage);\n }\n\n /**\n * Batch read multiple opportunities by their CRM IDs\n *\n * @param array<string> $crmIds Array of HubSpot deal IDs (max 100)\n * @param array<string> $fields Array of property names to fetch\n *\n * @return array<string, array> Array keyed by CRM ID with opportunity data\n */\n public function getOpportunitiesByIds(array $crmIds, array $fields): array\n {\n return $this->batchReadObjects('deals', $crmIds, $fields);\n }\n\n /**\n * Batch read multiple companies by their CRM IDs\n *\n * @param array<string> $crmIds Array of HubSpot company IDs (max 100)\n * @param array<string> $fields Array of property names to fetch\n *\n * @return array<string, array> Array keyed by CRM ID with company data\n */\n public function getCompaniesByIds(array $crmIds, array $fields): array\n {\n return $this->batchReadObjects('companies', $crmIds, $fields);\n }\n\n /**\n * Batch read multiple contacts by their CRM IDs\n *\n * @param array<string> $crmIds Array of HubSpot contact IDs (max 100)\n * @param array<string> $fields Array of property names to fetch\n *\n * @return array<string, array> Array keyed by CRM ID with contact data\n */\n public function getContactsByIds(array $crmIds, array $fields): array\n {\n return $this->batchReadObjects('contacts', $crmIds, $fields);\n }\n\n /**\n * @throws CompanyApiException\n * @throws CrmException\n */\n public function getAccountById(string $crmId, array $fields): array\n {\n try {\n $company = $this->getNewInstance()->crm()->companies()->basicApi()->getById(\n $crmId,\n implode(',', $fields),\n );\n } catch (CompanyApiException $e) {\n $this->log->info('[Hubspot] Failed to fetch account', [\n 'crm_id' => $crmId,\n 'reason' => $e->getMessage(),\n ]);\n\n throw $e;\n }\n\n if (! $company instanceof CompaniesWithAssociations) {\n throw new CrmException('Account not found');\n }\n\n return [\n 'id' => $company->getId(),\n 'properties' => $company->getProperties(),\n ];\n }\n\n /**\n * @throws ContactApiException\n * @throws CrmException\n */\n public function getContactById(string $crmId, array $fields): array\n {\n try {\n $contact = $this->getNewInstance()->crm()->contacts()->basicApi()->getById(\n $crmId,\n implode(',', $fields)\n );\n } catch (ContactApiException $e) {\n $this->log->info('[Hubspot] Failed to fetch contact', [\n 'crm_id' => $crmId,\n 'reason' => $e->getMessage(),\n ]);\n\n throw $e;\n }\n\n if (! $contact instanceof ContactsWithAssociations) {\n throw new CrmException('Contact not found');\n }\n\n return [\n 'id' => $contact->getId(),\n 'properties' => $contact->getProperties(),\n ];\n }\n\n /**\n * This is email search request that Hubspot offers as GET (more generous quota)\n */\n public function getContactByEmail(string $email, array $fields = []): array\n {\n try {\n $contact = $this->getNewInstance()->crm()->contacts()->basicApi()->getById(\n $email,\n implode(',', $fields),\n null,\n false,\n 'email'\n );\n\n return [\n 'id' => $contact->getId(),\n 'properties' => $contact->getProperties(),\n ];\n } catch (ContactApiException $e) {\n $this->log->info('[Hubspot] Failed to fetch contact', [\n 'email' => $email,\n 'reason' => $e->getMessage(),\n ]);\n\n return [];\n }\n }\n\n /**\n * @throws CrmException\n */\n public function fetchProperty(string $objectType, string $propertyId): Property\n {\n $result = $this->getNewInstance()->crm()->properties()->coreApi()->getByName($objectType, $propertyId);\n\n if (! $result instanceof Property) {\n $this->log->error('[Hubspot] Failed to fetch property', [\n 'object_type' => $objectType,\n 'property_id' => $propertyId,\n 'reason' => $result->getMessage(),\n ]);\n\n throw new CrmException('Failed to fetch property');\n }\n\n return $result;\n }\n\n /**\n * @return array<CrmFieldOption>\n */\n public function fetchPropertyOptions(string $objectType, string $propertyId): array\n {\n /** @var array<CrmFieldOption> */\n return $this->fetchProperty($objectType, $propertyId)->getOptions();\n }\n\n /**\n * @return array<array{id:string, label:string, deleted:bool}>\n */\n public function fetchCallDispositions(): array\n {\n /** @var Response $response */\n $response = $this->getInstance()->engagements()->getCallDispositions();\n\n /**\n * @var array<array{\n * id:string,\n * label:string,\n * deleted: bool\n * }>\n */\n return $response->toArray();\n }\n\n /**\n * @return array<CrmFieldOption>\n */\n public function fetchOpportunityPipelineStages(): array\n {\n $stages = [];\n $apiResponse = $this->getNewInstance()->crm()->pipelines()->pipelinesApi()->getAll('deals');\n\n if ($apiResponse instanceof Error) {\n $this->log->error('[Hubspot] Failed to fetch opportunity pipelines', [\n 'reason' => $apiResponse->getMessage(),\n ]);\n\n return [];\n }\n\n foreach ($apiResponse->getResults() as $pipeline) {\n $pipelineStages = array_map(\n static function (PipelineStage $stage) {\n return [\n 'id' => $stage->getId(),\n 'label' => $stage->getLabel(),\n ];\n },\n $pipeline->getStages()\n );\n\n $stages = array_merge($stages, $pipelineStages);\n }\n\n return $stages;\n }\n\n public function fetchOpportunityPipelines(): array\n {\n $pipelines = [];\n\n try {\n $apiResponse = $this->makeRequest('/crm/v3/pipelines/deals');\n } catch (\\Exception $e) {\n $this->log->info('[Hubspot] Failed to fetch opportunity pipelines', [\n 'reason' => $e->getMessage(),\n ]);\n\n return [];\n }\n\n $response = $apiResponse->toArray();\n\n foreach ($response['results'] as $pipeline) {\n $pipelines[] = [\n 'id' => $pipeline['id'],\n 'label' => $pipeline['label'],\n ];\n }\n\n return $pipelines;\n }\n\n /**\n * @return array<CrmFieldOption>\n */\n public function fetchMeetingOutcomeFieldOptions(Field $field): array\n {\n return $field->getCrmProviderId() === 'meetingOutcome'\n ? $this->fetchMeetingOutcomeTypes()\n : $this->fetchCallActivityTypes();\n }\n\n public function fetchMeetingOutcomeTypes(): array\n {\n return $this->extractMeetingTypeOptions(\n 'https://api.hubapi.com/crm/v3/properties/meeting/hs_meeting_outcome'\n );\n }\n\n public function fetchCallActivityTypes(): array\n {\n return $this->extractMeetingTypeOptions(\n 'https://api.hubapi.com/crm/v3/properties/call/hs_activity_type'\n );\n }\n\n private function extractMeetingTypeOptions(string $endpoint): array\n {\n /** @var Response $response */\n $response = $this->getInstance()\n ->getClient()\n ->request('GET', $endpoint);\n\n /**\n * @var array<array{\n * value: string,\n * label: string,\n * displayOrder: int\n * }> $optionData\n */\n $optionData = $response->toArray()['options'] ?? [];\n\n $options = [];\n foreach ($optionData as $item) {\n $options[] = [\n 'id' => $item['value'],\n 'value' => $item['value'],\n 'label' => $item['label'],\n 'display_order' => $item['displayOrder'],\n ];\n }\n\n return $options;\n }\n\n /**\n * @return array<CrmFieldOption>\n */\n public function fetchDispositionFieldOptions(): array\n {\n $options = [];\n\n $dispositions = $this->fetchCallDispositions();\n\n foreach ($dispositions as $disposition) {\n if ($disposition['deleted'] !== false) {\n continue;\n }\n\n $option['value'] = $disposition['id'];\n $option['id'] = $disposition['id'];\n $option['label'] = $disposition['label'];\n\n $options[] = $option;\n }\n\n return $options;\n }\n\n /**\n * @return array<CrmFieldOption>\n */\n public function fetchOpportunityFieldOptions(Field $field): array\n {\n if ($field->isStageField()) {\n return $this->fetchOpportunityPipelineStages();\n }\n\n if ($field->isPipelineField()) {\n return $this->fetchOpportunityPipelines();\n }\n\n return $this->fetchPropertyOptions('deals', $field->getCrmProviderId());\n }\n\n /**\n * @throws BadRequest\n * @throws HubspotException\n */\n public function makeRequest(string $endpoint, $method = 'GET', $payload = [], ?string $queryString = null)\n {\n $endpoint = self::BASE_URL . $endpoint;\n\n if ($method === 'GET') {\n return $this->getInstance()->getClient()?->request(\n method: $method,\n endpoint: $endpoint,\n query_string: $queryString\n );\n } else {\n return $this->getInstance()->getClient()->request($method, $endpoint, [\n 'json' => ($payload),\n ]);\n }\n }\n\n /**\n * @throws BadRequest\n * @throws HubspotException\n */\n public function createMeeting(array $payload): Response\n {\n $endpoint = '/crm/v3/objects/meetings';\n\n return $this->makeRequest($endpoint, 'POST', $payload);\n }\n\n /**\n * @throws BadRequest\n * @throws HubspotException\n */\n public function updateMeeting(string $meetingId, array $payload): Response\n {\n $endpoint = '/crm/v3/objects/meetings/' . $meetingId;\n\n return $this->makeRequest($endpoint, 'PATCH', $payload);\n }\n\n /**\n * @throws \\Exception\n */\n public function createNote(\n string $body,\n string $ownerId,\n int $timestamp,\n string $objectId,\n NoteObject $noteObject\n ): ?string {\n try {\n $noteInput = new SimplePublicObjectInput([\n 'properties' => [\n 'hs_note_body' => $body,\n 'hubspot_owner_id' => $ownerId,\n 'hs_timestamp' => $timestamp,\n ],\n ]);\n\n // Create note\n $note = $this->getNewInstance()->crm()->objects()->basicApi()->create('note', $noteInput);\n\n $this->getNewInstance()->crm()->objects()->associationsApi()->create(\n 'note',\n $note->getId(),\n $this->getNoteObject($noteObject),\n $objectId,\n $this->getNoteAssociationType($noteObject),\n );\n\n return $note->getId();\n } catch (\\Exception $e) {\n $this->log->error('[Hubspot] Failed to create note', [\n 'objectId' => $objectId,\n 'noteObject' => $noteObject->getObjectType(),\n 'reason' => $e->getMessage(),\n ]);\n\n \\Sentry::captureException($e);\n }\n\n return null;\n }\n\n public function updateEngagement(string $objectId, array $engagement, array $metadata): void\n {\n $this->getInstance()->engagements()->update($objectId, $engagement, $metadata);\n }\n\n public function getEngagementData(string $engagementId): array\n {\n $engagement = $this->getInstance()->engagements()->get($engagementId);\n\n return $engagement->toArray();\n }\n\n public function createEngagement(array $engagement, array $associations, array $metadata): Response\n {\n return $this->getInstance()\n ->engagements()\n ->create($engagement, $associations, $metadata);\n }\n\n public function isUnauthorizedException(\\Exception $e): bool\n {\n // Check for specific HubSpot API exception types first\n if ($e instanceof BadRequest) {\n // BadRequest can contain 401 status codes\n return $e->getCode() === 401;\n }\n\n // Check for HTTP client exceptions with status codes\n if ($e instanceof \\GuzzleHttp\\Exception\\RequestException && $e->hasResponse()) {\n $response = $e->getResponse();\n if ($response !== null) {\n return $response->getStatusCode() === 401;\n }\n }\n\n // Check for Guzzle HTTP exceptions\n if ($e instanceof \\GuzzleHttp\\Exception\\ClientException) {\n return $e->getCode() === 401;\n }\n\n // Fallback to string matching as last resort, but be more specific\n $message = strtolower($e->getMessage());\n\n return str_contains($message, '401 unauthorized') ||\n str_contains($message, 'http 401') ||\n str_contains($message, 'status code 401') ||\n (preg_match('/\\b401\\b/', $message) && str_contains($message, 'unauthorized'));\n }\n\n /**\n * Validates and refreshes the access token if needed before API requests.\n * This ensures long-running processes don't fail due to token expiration.\n *\n * @throws SocialAccountTokenInvalidException\n */\n public function ensureValidToken(): void\n {\n if ($this->oauthAccount === null) {\n return;\n }\n\n $newToken = $this->tokenManager->ensureValidToken($this->oauthAccount);\n if ($newToken !== null) {\n $this->accessToken = $newToken;\n }\n }\n\n public function getConfig()\n {\n return $this->config;\n }\n\n // returns only active (archived=false)\n public function getOwners(): array\n {\n return $this->getNewInstance()->crm()->owners()->getAll();\n }\n\n /**\n * @param bool $archived\n *\n * @return array<Owner>|[]\n */\n public function getOwnersArchived(bool $archived = true): array\n {\n $endpoint = '/crm/v3/owners';\n $queryParams = [\n 'archived' => $archived ? 'true' : 'false',\n ];\n $queryString = http_build_query($queryParams);\n\n $owners = [];\n\n try {\n $response = $this->makeRequest(endpoint: $endpoint, queryString: $queryString);\n $responseData = $response?->toArray();\n\n foreach ($responseData['results'] as $result) {\n try {\n $owners[] = Owner::create($result);\n } catch (Throwable $e) {\n $this->log->error('[HubSpot] Failed to process owner data', [\n 'result' => $result,\n 'error' => $e->getMessage(),\n ]);\n\n continue;\n }\n }\n } catch (Throwable $e) {\n $this->log->error('HubSpot] Failed to fetch owners', [\n 'archived' => $archived,\n 'error' => $e->getMessage(),\n ]);\n\n return [];\n }\n\n return $owners;\n }\n\n public function getMeeting(string $engagementId): ObjectWithAssociations\n {\n return $this->getNewInstance()->crm()->objects()->basicApi()\n ->getById('meeting', $engagementId, null, 'contact,company,deal');\n }\n\n public function deleteEngagement(string $engagementId): void\n {\n $this->getInstance()->engagements()->delete((int) $engagementId);\n }\n\n public function getAssociationsData(array $ids, string $fromObject, string $toObject): array\n {\n $associationData = [];\n $idChunks = array_chunk($ids, self::ASSOCIATIONS_BATCH_SIZE_LIMIT);\n\n foreach ($idChunks as $idChunk) {\n try {\n $batchInput = new \\HubSpot\\Client\\Crm\\Associations\\Model\\BatchInputPublicObjectId();\n $batchInput->setInputs(array_map(function ($id) {\n $publicObjectId = new \\HubSpot\\Client\\Crm\\Associations\\Model\\PublicObjectId();\n $publicObjectId->setId($id);\n\n return $publicObjectId;\n }, $idChunk));\n\n $associatedObjectsData = $this\n ->getNewInstance()\n ->crm()\n ->associations()\n ->batchApi()\n ->read($fromObject, $toObject, $batchInput);\n\n if ($associatedObjectsData instanceof \\HubSpot\\Client\\Crm\\Associations\\Model\\BatchResponsePublicAssociationMulti) {\n foreach ($associatedObjectsData->getResults() as $association) {\n $from = $association->getFrom()->getId();\n $toAssociations = $association->getTo();\n\n if (! empty($toAssociations)) {\n $associationData[$from] = array_map(function ($item) {\n return $item->getId();\n }, $toAssociations);\n }\n }\n }\n } catch (\\Exception $e) {\n $this->log->error('[Hubspot] Failed to fetch associations', [\n 'from_object' => $fromObject,\n 'to_object' => $toObject,\n 'reason' => $e->getMessage(),\n ]);\n }\n }\n\n return $associationData;\n }\n\n /**\n * @throws \\Exception\n */\n private function getNoteAssociationType(NoteObject $noteObject): string\n {\n return match($noteObject) {\n NoteObject::Opportunity => 'note_to_deal',\n NoteObject::Lead, NoteObject::Contact => 'note_to_contact', // or 'note_to_lead' if your portal supports it\n NoteObject::Account => 'note_to_company',\n NoteObject::Call, NoteObject::Event => throw new \\Exception('Not supported'),\n };\n }\n\n /**\n * @throws \\Exception\n */\n private function getNoteObject(NoteObject $noteObject): string\n {\n return match($noteObject) {\n NoteObject::Opportunity => 'deal',\n NoteObject::Lead, NoteObject::Contact => 'contact',\n NoteObject::Account => 'company',\n NoteObject::Call, NoteObject::Event => throw new \\Exception('Not supported'),\n };\n }\n\n public function addAssociations(string $objectType, string $associationType, array $payload): Response\n {\n $endpoint = \"/crm/v4/associations/$objectType/$associationType/batch/create\";\n\n return $this->makeRequest($endpoint, 'POST', $payload);\n }\n\n public function removeAssociations(string $objectType, string $associationType, array $payload): Response\n {\n $endpoint = \"/crm/v4/associations/$objectType/$associationType/batch/archive\";\n\n return $this->makeRequest($endpoint, 'POST', $payload);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Hubspot;\n\nuse HubSpot\\Client\\Crm\\Deals\\ApiException as DealApiException;\nuse HubSpot\\Client\\Crm\\Contacts\\ApiException as ContactApiException;\nuse HubSpot\\Client\\Crm\\Companies\\ApiException as CompanyApiException;\nuse HubSpot\\Client\\Crm\\Contacts\\Model\\SimplePublicObjectWithAssociations as ContactsWithAssociations;\nuse HubSpot\\Client\\Crm\\Companies\\Model\\SimplePublicObjectWithAssociations as CompaniesWithAssociations;\nuse HubSpot\\Client\\Crm\\Deals\\Model\\SimplePublicObjectWithAssociations as DealWithAssociations;\nuse HubSpot\\Client\\Crm\\Objects\\Model\\SimplePublicObjectInput;\nuse HubSpot\\Client\\Crm\\Objects\\Model\\SimplePublicObjectWithAssociations as ObjectWithAssociations;\nuse HubSpot\\Client\\Crm\\Pipelines\\Model\\Error;\nuse HubSpot\\Client\\Crm\\Pipelines\\Model\\PipelineStage;\nuse HubSpot\\Client\\Crm\\Properties\\Model\\Property;\nuse HubSpot\\Discovery\\Discovery;\nuse Jiminny\\Exceptions\\CrmException;\nuse Jiminny\\Exceptions\\RateLimitException;\nuse Jiminny\\Exceptions\\SocialAccountTokenInvalidException;\nuse Jiminny\\Jobs\\Crm\\NoteObject;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Services\\Crm\\BaseClient;\nuse Jiminny\\Services\\Crm\\Hubspot\\DTO\\Response\\Owner;\nuse Jiminny\\Services\\SocialAccountService;\nuse SevenShores\\Hubspot\\Exceptions\\BadRequest;\nuse SevenShores\\Hubspot\\Exceptions\\HubspotException;\nuse SevenShores\\Hubspot\\Factory;\nuse SevenShores\\Hubspot\\Http\\Response;\nuse Jiminny\\Services\\Crm\\Hubspot\\Pagination\\HubspotPaginationService;\nuse Illuminate\\Support\\Facades\\Redis;\nuse Throwable;\n\n/**\n * @phpstan-type CrmFieldOption array{id:string, label:string, value?:string}\n */\nclass Client extends BaseClient implements HubspotClientInterface\n{\n public const string MIN_API_VERSION = '2';\n\n public const string BASE_URL = 'https://api.hubapi.com';\n\n public const int ASSOCIATIONS_BATCH_SIZE_LIMIT = 1000;\n\n private HubspotPaginationService $paginationService;\n private HubspotTokenManager $tokenManager;\n\n public function __construct(\n SocialAccountService $socialAccountService,\n HubspotPaginationService $paginationService,\n HubspotTokenManager $tokenManager\n ) {\n parent::__construct($socialAccountService);\n $this->paginationService = $paginationService;\n $this->tokenManager = $tokenManager;\n\n $this->setBaseUrl(self::BASE_URL);\n $this->setVersion(self::MIN_API_VERSION);\n }\n\n /**\n * Execute a HubSpot API call with rate limit handling.\n *\n * On a 429, stores the absolute expiry timestamp with SET NX (first writer wins).\n * This means all subsequent jobs that also receive 429 in the same burst do not\n * reset the TTL — the window is anchored to the first 429, not the last.\n * Readers compute the remaining wait from the stored timestamp, so jobs that check\n * the cache near expiry are not delayed longer than necessary.\n *\n * @template T\n *\n * @param callable(): T $apiCall The API call to execute\n *\n * @throws RateLimitException When rate limit is hit or cached rate limit is active\n *\n * @return T The result of the API call\n */\n private function executeRequest(callable $apiCall)\n {\n $cacheKey = $this->getRateLimitCacheKey();\n\n $cachedExpiresAt = Redis::get($cacheKey);\n if (is_string($cachedExpiresAt) && is_numeric($cachedExpiresAt)) {\n $remaining = max(1, (int) $cachedExpiresAt - time());\n\n throw new RateLimitException(\n 'Hubspot rate limit (cached circuit-breaker)',\n $remaining,\n );\n }\n\n try {\n return $apiCall();\n } catch (Throwable $e) {\n if ($this->isHubspotRateLimit($e)) {\n $retryAfter = $this->parseRetryAfter($e);\n\n // NX: only the first job to receive a 429 in this burst sets the key.\n // Subsequent 429s in the same burst leave the TTL untouched so the\n // window is not reset by every concurrent job hitting the limit.\n Redis::set($cacheKey, (string) (time() + $retryAfter), 'EX', $retryAfter, 'NX');\n\n $this->log->warning('[Hubspot] Received 429 from API', [\n 'team_id' => $this->config->team_id,\n 'config_id' => $this->config->getId(),\n 'retry_after' => $retryAfter,\n 'reason' => $e->getMessage(),\n ]);\n\n throw new RateLimitException('Hubspot returned 429', $retryAfter, $e);\n }\n\n throw $e;\n }\n }\n\n private function getRateLimitCacheKey(): string\n {\n return sprintf('hubspot:ratelimit:config:%d', $this->config->getId());\n }\n\n private function isHubspotRateLimit(Throwable $e): bool\n {\n if ($e instanceof BadRequest\n || $e instanceof DealApiException\n || $e instanceof ContactApiException\n || $e instanceof CompanyApiException\n || $e instanceof \\GuzzleHttp\\Exception\\RequestException\n ) {\n return (int) $e->getCode() === 429;\n }\n\n return false;\n }\n\n private function parseRetryAfter(Throwable $e): int\n {\n if (method_exists($e, 'getResponseHeaders')) {\n $headers = $e->getResponseHeaders() ?: [];\n $value = $headers['Retry-After'] ?? $headers['retry-after'] ?? null;\n if (is_array($value)) {\n $value = $value[0] ?? null;\n }\n if (is_numeric($value)) {\n return (int) $value;\n }\n }\n\n $message = strtolower($e->getMessage());\n\n if (str_contains($message, 'daily')) {\n return 600;\n }\n if (str_contains($message, 'ten secondly')) {\n return 10;\n }\n if (str_contains($message, 'secondly')) {\n return 1;\n }\n\n $this->log->warning('[Hubspot] No retry-after header or known message, using default', [\n 'exception_class' => get_class($e),\n 'message' => $message,\n ]);\n\n return 10;\n }\n\n public function getMinimumApiVersion(): string\n {\n return self::MIN_API_VERSION;\n }\n\n public function getInstance(): Factory\n {\n return new Factory([\n 'key' => $this->accessToken,\n 'oauth2' => true,\n 'base_url' => $this->baseUrl,\n ]);\n }\n\n public function getNewInstance(): Discovery\n {\n return \\HubSpot\\Factory::createWithAccessToken($this->accessToken);\n }\n\n /**\n * Secondly and daily limits for Hubspot API\n *\n * Product Tier: Free & Starter | Professional & Enterprise | API add-on (any tier)\n * Burst: 100/10 seconds | 150/10 seconds | 200/10 seconds\n * Daily: 250,000 | 500,000 | 1,000,000\n *\n * Official documentation states: The search endpoints are rate limited to five requests per second.\n * Since with 5 RPS were still hitting secondly rate limits we lowered it to 4\n */\n public function getPaginatedData(array $payload, string $type, int $offset = 0): array\n {\n $total = 0;\n $lastId = null;\n $rows = [];\n foreach ($this->getPaginatedDataGenerator($payload, $type, $offset, $total, $lastId) as $row) {\n $rows[] = $row;\n }\n\n return ['results' => $rows, 'total' => $total, 'last_record' => $lastId];\n }\n\n /**\n * @throws HubspotException\n * @throws SocialAccountTokenInvalidException\n * @throws BadRequest\n */\n public function getPaginatedDataGenerator(\n array $payload,\n string $type,\n int $offset = 0,\n int &$total = 0,\n ?string &$lastRecordId = null\n ): \\Generator {\n return $this->paginationService->getPaginatedDataGenerator(\n $this,\n $payload,\n $type,\n $offset,\n $total,\n $lastRecordId\n );\n }\n\n /**\n * Execute a search request against HubSpot CRM objects with rate limiting.\n *\n * @param string $objectType The object type ('deals', 'companies', 'contacts', 'calls')\n * @param array<string, mixed> $payload The search payload with filters, sorts, properties, etc.\n *\n * @throws RateLimitException When rate limit is hit\n * @throws HubspotException On API errors\n *\n * @return array The search response with 'results', 'total', 'paging' keys\n */\n public function search(string $objectType, array $payload): array\n {\n $endpoint = self::BASE_URL . \"/crm/v3/objects/{$objectType}/search\";\n\n return $this->executeRequest(function () use ($endpoint, $payload) {\n $response = $this->getInstance()->getClient()->request('POST', $endpoint, ['json' => $payload]);\n\n return $response->toArray();\n });\n }\n\n /**\n * @throws DealApiException\n * @throws CrmException\n */\n public function getOpportunityById(string $crmId, array $fields): array\n {\n try {\n $deal = $this->getNewInstance()->crm()->deals()->basicApi()->getById(\n $crmId,\n implode(',', $fields),\n 'companies,contacts'\n );\n } catch (DealApiException $e) {\n $this->log->info('[Hubspot] Failed to fetch opportunity', [\n 'crm_id' => $crmId,\n 'reason' => $e->getMessage(),\n ]);\n\n throw $e;\n }\n\n if (! $deal instanceof DealWithAssociations) {\n throw new CrmException('Deal not found');\n }\n\n return [\n 'id' => $deal->getId(),\n 'properties' => $deal->getProperties(),\n 'associations' => $deal->getAssociations(),\n ];\n }\n\n /**\n * Generic batch read method for HubSpot objects\n *\n * @param string $objectType The object type ('deals', 'companies', 'contacts')\n * @param array<string> $crmIds Array of HubSpot object IDs (max 100)\n * @param array<string> $fields Array of property names to fetch\n *\n * @return array<string, array> Array keyed by CRM ID with object data\n */\n private function batchReadObjects(string $objectType, array $crmIds, array $fields): array\n {\n if (empty($crmIds)) {\n return [];\n }\n\n $this->validateBatchSize($objectType, $crmIds);\n $this->ensureValidToken();\n\n try {\n $batchConfig = $this->createBatchConfiguration($objectType);\n $batchReadRequest = $this->prepareBatchRequest($batchConfig, $crmIds, $fields);\n $response = $batchConfig['api']->read($batchReadRequest);\n\n $this->validateApiResponse($response, $objectType);\n\n $results = $this->processApiResults($response);\n $this->logBatchResults($objectType, $crmIds, $results);\n\n return $results;\n } catch (\\Throwable $e) {\n $this->handleBatchError($e, $objectType, $crmIds);\n }\n }\n\n private function validateBatchSize(string $objectType, array $crmIds): void\n {\n if (count($crmIds) > 100) {\n throw new \\InvalidArgumentException(\"Batch size cannot exceed 100 {$objectType}\");\n }\n }\n\n private function createBatchConfiguration(string $objectType): array\n {\n $configurations = [\n 'deals' => [\n 'batchReadRequest' => new \\HubSpot\\Client\\Crm\\Deals\\Model\\BatchReadInputSimplePublicObjectId(),\n 'inputClass' => \\HubSpot\\Client\\Crm\\Deals\\Model\\SimplePublicObjectId::class,\n 'api' => $this->getNewInstance()->crm()->deals()->batchApi(),\n ],\n 'companies' => [\n 'batchReadRequest' => new \\HubSpot\\Client\\Crm\\Companies\\Model\\BatchReadInputSimplePublicObjectId(),\n 'inputClass' => \\HubSpot\\Client\\Crm\\Companies\\Model\\SimplePublicObjectId::class,\n 'api' => $this->getNewInstance()->crm()->companies()->batchApi(),\n ],\n 'contacts' => [\n 'batchReadRequest' => new \\HubSpot\\Client\\Crm\\Contacts\\Model\\BatchReadInputSimplePublicObjectId(),\n 'inputClass' => \\HubSpot\\Client\\Crm\\Contacts\\Model\\SimplePublicObjectId::class,\n 'api' => $this->getNewInstance()->crm()->contacts()->batchApi(),\n ],\n ];\n\n if (! isset($configurations[$objectType])) {\n throw new \\InvalidArgumentException(\"Unsupported object type: {$objectType}\");\n }\n\n return $configurations[$objectType];\n }\n\n private function prepareBatchRequest(array $batchConfig, array $crmIds, array $fields): object\n {\n $batchReadRequest = $batchConfig['batchReadRequest'];\n $inputClass = $batchConfig['inputClass'];\n\n $inputs = array_map(function ($crmId) use ($inputClass) {\n $input = new $inputClass();\n $input->setId($crmId);\n\n return $input;\n }, $crmIds);\n\n $batchReadRequest->setInputs($inputs);\n $batchReadRequest->setProperties($fields);\n\n return $batchReadRequest;\n }\n\n private function validateApiResponse($response, string $objectType): void\n {\n if (! $response) {\n throw new CrmException(\"HubSpot API returned null response for {$objectType} batch read\");\n }\n }\n\n private function processApiResults($response): array\n {\n $results = [];\n $responseResults = $response->getResults();\n\n if ($responseResults) {\n foreach ($responseResults as $object) {\n if ($object && $object->getId()) {\n $results[$object->getId()] = [\n 'id' => $object->getId(),\n 'properties' => $object->getProperties() ?: [],\n ];\n }\n }\n }\n\n return $results;\n }\n\n private function logBatchResults(string $objectType, array $crmIds, array $results): void\n {\n $this->log->info(\"[HubSpot] Batch fetched {$objectType}\", [\n 'requested_count' => count($crmIds),\n 'returned_count' => count($results),\n 'crm_ids' => $crmIds,\n ]);\n }\n\n private function handleBatchError(\\Throwable $e, string $objectType, array $crmIds): void\n {\n $errorMessage = $e->getMessage() ?: 'Unknown error';\n $errorTrace = $e->getTraceAsString() ?: 'No trace available';\n\n $this->log->error(\"[HubSpot] Failed to batch fetch {$objectType}\", [\n 'crm_ids' => $crmIds,\n 'error' => $errorMessage,\n 'trace' => $errorTrace,\n ]);\n\n throw new CrmException(\"Failed to batch fetch {$objectType}: \" . $errorMessage);\n }\n\n /**\n * Batch read multiple opportunities by their CRM IDs\n *\n * @param array<string> $crmIds Array of HubSpot deal IDs (max 100)\n * @param array<string> $fields Array of property names to fetch\n *\n * @return array<string, array> Array keyed by CRM ID with opportunity data\n */\n public function getOpportunitiesByIds(array $crmIds, array $fields): array\n {\n return $this->batchReadObjects('deals', $crmIds, $fields);\n }\n\n /**\n * Batch read multiple companies by their CRM IDs\n *\n * @param array<string> $crmIds Array of HubSpot company IDs (max 100)\n * @param array<string> $fields Array of property names to fetch\n *\n * @return array<string, array> Array keyed by CRM ID with company data\n */\n public function getCompaniesByIds(array $crmIds, array $fields): array\n {\n return $this->batchReadObjects('companies', $crmIds, $fields);\n }\n\n /**\n * Batch read multiple contacts by their CRM IDs\n *\n * @param array<string> $crmIds Array of HubSpot contact IDs (max 100)\n * @param array<string> $fields Array of property names to fetch\n *\n * @return array<string, array> Array keyed by CRM ID with contact data\n */\n public function getContactsByIds(array $crmIds, array $fields): array\n {\n return $this->batchReadObjects('contacts', $crmIds, $fields);\n }\n\n /**\n * @throws CompanyApiException\n * @throws CrmException\n */\n public function getAccountById(string $crmId, array $fields): array\n {\n try {\n $company = $this->getNewInstance()->crm()->companies()->basicApi()->getById(\n $crmId,\n implode(',', $fields),\n );\n } catch (CompanyApiException $e) {\n $this->log->info('[Hubspot] Failed to fetch account', [\n 'crm_id' => $crmId,\n 'reason' => $e->getMessage(),\n ]);\n\n throw $e;\n }\n\n if (! $company instanceof CompaniesWithAssociations) {\n throw new CrmException('Account not found');\n }\n\n return [\n 'id' => $company->getId(),\n 'properties' => $company->getProperties(),\n ];\n }\n\n /**\n * @throws ContactApiException\n * @throws CrmException\n */\n public function getContactById(string $crmId, array $fields): array\n {\n try {\n $contact = $this->getNewInstance()->crm()->contacts()->basicApi()->getById(\n $crmId,\n implode(',', $fields)\n );\n } catch (ContactApiException $e) {\n $this->log->info('[Hubspot] Failed to fetch contact', [\n 'crm_id' => $crmId,\n 'reason' => $e->getMessage(),\n ]);\n\n throw $e;\n }\n\n if (! $contact instanceof ContactsWithAssociations) {\n throw new CrmException('Contact not found');\n }\n\n return [\n 'id' => $contact->getId(),\n 'properties' => $contact->getProperties(),\n ];\n }\n\n /**\n * This is email search request that Hubspot offers as GET (more generous quota)\n */\n public function getContactByEmail(string $email, array $fields = []): array\n {\n try {\n $contact = $this->getNewInstance()->crm()->contacts()->basicApi()->getById(\n $email,\n implode(',', $fields),\n null,\n false,\n 'email'\n );\n\n return [\n 'id' => $contact->getId(),\n 'properties' => $contact->getProperties(),\n ];\n } catch (ContactApiException $e) {\n $this->log->info('[Hubspot] Failed to fetch contact', [\n 'email' => $email,\n 'reason' => $e->getMessage(),\n ]);\n\n return [];\n }\n }\n\n /**\n * @throws CrmException\n */\n public function fetchProperty(string $objectType, string $propertyId): Property\n {\n $result = $this->getNewInstance()->crm()->properties()->coreApi()->getByName($objectType, $propertyId);\n\n if (! $result instanceof Property) {\n $this->log->error('[Hubspot] Failed to fetch property', [\n 'object_type' => $objectType,\n 'property_id' => $propertyId,\n 'reason' => $result->getMessage(),\n ]);\n\n throw new CrmException('Failed to fetch property');\n }\n\n return $result;\n }\n\n /**\n * @return array<CrmFieldOption>\n */\n public function fetchPropertyOptions(string $objectType, string $propertyId): array\n {\n /** @var array<CrmFieldOption> */\n return $this->fetchProperty($objectType, $propertyId)->getOptions();\n }\n\n /**\n * @return array<array{id:string, label:string, deleted:bool}>\n */\n public function fetchCallDispositions(): array\n {\n /** @var Response $response */\n $response = $this->getInstance()->engagements()->getCallDispositions();\n\n /**\n * @var array<array{\n * id:string,\n * label:string,\n * deleted: bool\n * }>\n */\n return $response->toArray();\n }\n\n /**\n * @return array<CrmFieldOption>\n */\n public function fetchOpportunityPipelineStages(): array\n {\n $stages = [];\n $apiResponse = $this->getNewInstance()->crm()->pipelines()->pipelinesApi()->getAll('deals');\n\n if ($apiResponse instanceof Error) {\n $this->log->error('[Hubspot] Failed to fetch opportunity pipelines', [\n 'reason' => $apiResponse->getMessage(),\n ]);\n\n return [];\n }\n\n foreach ($apiResponse->getResults() as $pipeline) {\n $pipelineStages = array_map(\n static function (PipelineStage $stage) {\n return [\n 'id' => $stage->getId(),\n 'label' => $stage->getLabel(),\n ];\n },\n $pipeline->getStages()\n );\n\n $stages = array_merge($stages, $pipelineStages);\n }\n\n return $stages;\n }\n\n public function fetchOpportunityPipelines(): array\n {\n $pipelines = [];\n\n try {\n $apiResponse = $this->makeRequest('/crm/v3/pipelines/deals');\n } catch (\\Exception $e) {\n $this->log->info('[Hubspot] Failed to fetch opportunity pipelines', [\n 'reason' => $e->getMessage(),\n ]);\n\n return [];\n }\n\n $response = $apiResponse->toArray();\n\n foreach ($response['results'] as $pipeline) {\n $pipelines[] = [\n 'id' => $pipeline['id'],\n 'label' => $pipeline['label'],\n ];\n }\n\n return $pipelines;\n }\n\n /**\n * @return array<CrmFieldOption>\n */\n public function fetchMeetingOutcomeFieldOptions(Field $field): array\n {\n return $field->getCrmProviderId() === 'meetingOutcome'\n ? $this->fetchMeetingOutcomeTypes()\n : $this->fetchCallActivityTypes();\n }\n\n public function fetchMeetingOutcomeTypes(): array\n {\n return $this->extractMeetingTypeOptions(\n 'https://api.hubapi.com/crm/v3/properties/meeting/hs_meeting_outcome'\n );\n }\n\n public function fetchCallActivityTypes(): array\n {\n return $this->extractMeetingTypeOptions(\n 'https://api.hubapi.com/crm/v3/properties/call/hs_activity_type'\n );\n }\n\n private function extractMeetingTypeOptions(string $endpoint): array\n {\n /** @var Response $response */\n $response = $this->getInstance()\n ->getClient()\n ->request('GET', $endpoint);\n\n /**\n * @var array<array{\n * value: string,\n * label: string,\n * displayOrder: int\n * }> $optionData\n */\n $optionData = $response->toArray()['options'] ?? [];\n\n $options = [];\n foreach ($optionData as $item) {\n $options[] = [\n 'id' => $item['value'],\n 'value' => $item['value'],\n 'label' => $item['label'],\n 'display_order' => $item['displayOrder'],\n ];\n }\n\n return $options;\n }\n\n /**\n * @return array<CrmFieldOption>\n */\n public function fetchDispositionFieldOptions(): array\n {\n $options = [];\n\n $dispositions = $this->fetchCallDispositions();\n\n foreach ($dispositions as $disposition) {\n if ($disposition['deleted'] !== false) {\n continue;\n }\n\n $option['value'] = $disposition['id'];\n $option['id'] = $disposition['id'];\n $option['label'] = $disposition['label'];\n\n $options[] = $option;\n }\n\n return $options;\n }\n\n /**\n * @return array<CrmFieldOption>\n */\n public function fetchOpportunityFieldOptions(Field $field): array\n {\n if ($field->isStageField()) {\n return $this->fetchOpportunityPipelineStages();\n }\n\n if ($field->isPipelineField()) {\n return $this->fetchOpportunityPipelines();\n }\n\n return $this->fetchPropertyOptions('deals', $field->getCrmProviderId());\n }\n\n /**\n * @throws BadRequest\n * @throws HubspotException\n */\n public function makeRequest(string $endpoint, $method = 'GET', $payload = [], ?string $queryString = null)\n {\n $endpoint = self::BASE_URL . $endpoint;\n\n if ($method === 'GET') {\n return $this->getInstance()->getClient()?->request(\n method: $method,\n endpoint: $endpoint,\n query_string: $queryString\n );\n } else {\n return $this->getInstance()->getClient()->request($method, $endpoint, [\n 'json' => ($payload),\n ]);\n }\n }\n\n /**\n * @throws BadRequest\n * @throws HubspotException\n */\n public function createMeeting(array $payload): Response\n {\n $endpoint = '/crm/v3/objects/meetings';\n\n return $this->makeRequest($endpoint, 'POST', $payload);\n }\n\n /**\n * @throws BadRequest\n * @throws HubspotException\n */\n public function updateMeeting(string $meetingId, array $payload): Response\n {\n $endpoint = '/crm/v3/objects/meetings/' . $meetingId;\n\n return $this->makeRequest($endpoint, 'PATCH', $payload);\n }\n\n /**\n * @throws \\Exception\n */\n public function createNote(\n string $body,\n string $ownerId,\n int $timestamp,\n string $objectId,\n NoteObject $noteObject\n ): ?string {\n try {\n $noteInput = new SimplePublicObjectInput([\n 'properties' => [\n 'hs_note_body' => $body,\n 'hubspot_owner_id' => $ownerId,\n 'hs_timestamp' => $timestamp,\n ],\n ]);\n\n // Create note\n $note = $this->getNewInstance()->crm()->objects()->basicApi()->create('note', $noteInput);\n\n $this->getNewInstance()->crm()->objects()->associationsApi()->create(\n 'note',\n $note->getId(),\n $this->getNoteObject($noteObject),\n $objectId,\n $this->getNoteAssociationType($noteObject),\n );\n\n return $note->getId();\n } catch (\\Exception $e) {\n $this->log->error('[Hubspot] Failed to create note', [\n 'objectId' => $objectId,\n 'noteObject' => $noteObject->getObjectType(),\n 'reason' => $e->getMessage(),\n ]);\n\n \\Sentry::captureException($e);\n }\n\n return null;\n }\n\n public function updateEngagement(string $objectId, array $engagement, array $metadata): void\n {\n $this->getInstance()->engagements()->update($objectId, $engagement, $metadata);\n }\n\n public function getEngagementData(string $engagementId): array\n {\n $engagement = $this->getInstance()->engagements()->get($engagementId);\n\n return $engagement->toArray();\n }\n\n public function createEngagement(array $engagement, array $associations, array $metadata): Response\n {\n return $this->getInstance()\n ->engagements()\n ->create($engagement, $associations, $metadata);\n }\n\n public function isUnauthorizedException(\\Exception $e): bool\n {\n // Check for specific HubSpot API exception types first\n if ($e instanceof BadRequest) {\n // BadRequest can contain 401 status codes\n return $e->getCode() === 401;\n }\n\n // Check for HTTP client exceptions with status codes\n if ($e instanceof \\GuzzleHttp\\Exception\\RequestException && $e->hasResponse()) {\n $response = $e->getResponse();\n if ($response !== null) {\n return $response->getStatusCode() === 401;\n }\n }\n\n // Check for Guzzle HTTP exceptions\n if ($e instanceof \\GuzzleHttp\\Exception\\ClientException) {\n return $e->getCode() === 401;\n }\n\n // Fallback to string matching as last resort, but be more specific\n $message = strtolower($e->getMessage());\n\n return str_contains($message, '401 unauthorized') ||\n str_contains($message, 'http 401') ||\n str_contains($message, 'status code 401') ||\n (preg_match('/\\b401\\b/', $message) && str_contains($message, 'unauthorized'));\n }\n\n /**\n * Validates and refreshes the access token if needed before API requests.\n * This ensures long-running processes don't fail due to token expiration.\n *\n * @throws SocialAccountTokenInvalidException\n */\n public function ensureValidToken(): void\n {\n if ($this->oauthAccount === null) {\n return;\n }\n\n $newToken = $this->tokenManager->ensureValidToken($this->oauthAccount);\n if ($newToken !== null) {\n $this->accessToken = $newToken;\n }\n }\n\n public function getConfig()\n {\n return $this->config;\n }\n\n // returns only active (archived=false)\n public function getOwners(): array\n {\n return $this->getNewInstance()->crm()->owners()->getAll();\n }\n\n /**\n * @param bool $archived\n *\n * @return array<Owner>|[]\n */\n public function getOwnersArchived(bool $archived = true): array\n {\n $endpoint = '/crm/v3/owners';\n $queryParams = [\n 'archived' => $archived ? 'true' : 'false',\n ];\n $queryString = http_build_query($queryParams);\n\n $owners = [];\n\n try {\n $response = $this->makeRequest(endpoint: $endpoint, queryString: $queryString);\n $responseData = $response?->toArray();\n\n foreach ($responseData['results'] as $result) {\n try {\n $owners[] = Owner::create($result);\n } catch (Throwable $e) {\n $this->log->error('[HubSpot] Failed to process owner data', [\n 'result' => $result,\n 'error' => $e->getMessage(),\n ]);\n\n continue;\n }\n }\n } catch (Throwable $e) {\n $this->log->error('HubSpot] Failed to fetch owners', [\n 'archived' => $archived,\n 'error' => $e->getMessage(),\n ]);\n\n return [];\n }\n\n return $owners;\n }\n\n public function getMeeting(string $engagementId): ObjectWithAssociations\n {\n return $this->getNewInstance()->crm()->objects()->basicApi()\n ->getById('meeting', $engagementId, null, 'contact,company,deal');\n }\n\n public function deleteEngagement(string $engagementId): void\n {\n $this->getInstance()->engagements()->delete((int) $engagementId);\n }\n\n public function getAssociationsData(array $ids, string $fromObject, string $toObject): array\n {\n $associationData = [];\n $idChunks = array_chunk($ids, self::ASSOCIATIONS_BATCH_SIZE_LIMIT);\n\n foreach ($idChunks as $idChunk) {\n try {\n $batchInput = new \\HubSpot\\Client\\Crm\\Associations\\Model\\BatchInputPublicObjectId();\n $batchInput->setInputs(array_map(function ($id) {\n $publicObjectId = new \\HubSpot\\Client\\Crm\\Associations\\Model\\PublicObjectId();\n $publicObjectId->setId($id);\n\n return $publicObjectId;\n }, $idChunk));\n\n $associatedObjectsData = $this\n ->getNewInstance()\n ->crm()\n ->associations()\n ->batchApi()\n ->read($fromObject, $toObject, $batchInput);\n\n if ($associatedObjectsData instanceof \\HubSpot\\Client\\Crm\\Associations\\Model\\BatchResponsePublicAssociationMulti) {\n foreach ($associatedObjectsData->getResults() as $association) {\n $from = $association->getFrom()->getId();\n $toAssociations = $association->getTo();\n\n if (! empty($toAssociations)) {\n $associationData[$from] = array_map(function ($item) {\n return $item->getId();\n }, $toAssociations);\n }\n }\n }\n } catch (\\Exception $e) {\n $this->log->error('[Hubspot] Failed to fetch associations', [\n 'from_object' => $fromObject,\n 'to_object' => $toObject,\n 'reason' => $e->getMessage(),\n ]);\n }\n }\n\n return $associationData;\n }\n\n /**\n * @throws \\Exception\n */\n private function getNoteAssociationType(NoteObject $noteObject): string\n {\n return match($noteObject) {\n NoteObject::Opportunity => 'note_to_deal',\n NoteObject::Lead, NoteObject::Contact => 'note_to_contact', // or 'note_to_lead' if your portal supports it\n NoteObject::Account => 'note_to_company',\n NoteObject::Call, NoteObject::Event => throw new \\Exception('Not supported'),\n };\n }\n\n /**\n * @throws \\Exception\n */\n private function getNoteObject(NoteObject $noteObject): string\n {\n return match($noteObject) {\n NoteObject::Opportunity => 'deal',\n NoteObject::Lead, NoteObject::Contact => 'contact',\n NoteObject::Account => 'company',\n NoteObject::Call, NoteObject::Event => throw new \\Exception('Not supported'),\n };\n }\n\n public function addAssociations(string $objectType, string $associationType, array $payload): Response\n {\n $endpoint = \"/crm/v4/associations/$objectType/$associationType/batch/create\";\n\n return $this->makeRequest($endpoint, 'POST', $payload);\n }\n\n public function removeAssociations(string $objectType, string $associationType, array $payload): Response\n {\n $endpoint = \"/crm/v4/associations/$objectType/$associationType/batch/archive\";\n\n return $this->makeRequest($endpoint, 'POST', $payload);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"45","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"41","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"66","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993\nSELECT * FROM users WHERE id = 25061;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 994;\nSELECT * FROM crm_profiles WHERE user_id = 25061;\n\nselect * from crm_configurations where id = 834;\nSELECT * FROM teams WHERE id = 882;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;\n\nSELECT * FROM contacts where crm_configuration_id = 834;\nSELECT * FROM opportunities WHERE team_id = 933\n# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');\nAND id IN (8482561,18352941,19042734,19232139,19445140,19472541);\nSELECT * FROM opportunity_contacts\nWHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 485; #\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nselect crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id\nwhere crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')\n# and l.converted_at IS NOT NULL\n;\n\n# ********************************************************************\nSELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')\nand opportunity_id IS NULL\norder by id desc;\n\nSELECT * FROM teams WHERE id = 604; # 598\nSELECT * FROM activities WHERE id = 74410828; # chelseaw@allvoices.co\nSELECT * FROM accounts WHERE id = 20068382;\nSELECT * FROM accounts WHERE id = 35186038;\n\nSELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 559 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;\nselect * from sidekick_settings where team_id = 781;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100\n\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 711;\nSELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL\nand is_internal = 0 and status = 'completed'\norder by id desc;\n\nSELECT * FROM crm_layout_entities\nWHERE crm_layout_id IN (2352, 2353);\n;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 556 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;\nSELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;\nselect * from contacts\nwhere crm_configuration_id = 530\nand crm_provider_id = 872252;\n\nselect * from activities where crm_configuration_id = 530\nand user_id = 14343 and type like '%softphone%'\nand created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);\n\n\nSELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t\nJOIN crm_configurations c ON t.id = c.team_id\nWHERE t.status = 'active';\n\nSELECT * FROM teams where id = 1091;\nSELECT * FROM crm_configurations where team_id = 1091;\nSELECT * FROM activity_providers where team_id = 1091;\nSELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT * FROM teams WHERE name LIKE '%Leadventure%';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1091 and sa.provider = 'salesforce';\n\nSELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812\nSELECT * FROM teams where id = 862;\nSELECT * FROM crm_configurations where team_id = 862;\nSELECT * FROM activity_providers where team_id = 862;\nSELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT t.id, crm.id, crm.provider, ap.* FROM teams t\njoin crm_configurations crm on t.id = crm.team_id\njoin activity_providers ap on t.id = ap.team_id\nwhere t.status = 'active' and ap.is_enabled = 1\nand crm.provider = 'hubspot'\nand ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',\n 'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');\n\nSELECT * FROM teams where id = 1068;\nSELECT * FROM crm_configurations where team_id = 1068;\nSELECT * FROM activity_providers where team_id = 1068;\n\nSELECT * FROM activities a\nwhere crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')\nand a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'\n )\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by a.id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1068 and sa.provider = 'hubspot';\n\n# ********************************************************************\n# ********************************************************************\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262\nSELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\nselect * from crm_layouts where crm_configuration_id = 834;\nselect * from crm_layout_entities where crm_layout_id = 2780;\nselect * from crm_fields where id IN (321153,321192,321193,321194);\n\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1057 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8\n\nSELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20\n\nSELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10\n\nSELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #\n\nSELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;\nselect * from users where team_id = 51; # 7783\nSELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130\nselect * from activity_searches where user_id = 7783;\nselect * from activity_search_filters where activity_search_id IN (32291, 32292);\n\nSELECT asf.activity_search_id, asf.id, asf.value\nFROM activity_search_filters asf\nWHERE asf.filter = 'group_id'\nAND asf.value IN (\n SELECT CONCAT(\n HEX(SUBSTR(uuid, 5, 4)), '-',\n HEX(SUBSTR(uuid, 3, 2)), '-',\n HEX(SUBSTR(uuid, 1, 2)), '-',\n HEX(SUBSTR(uuid, 9, 2)), '-',\n HEX(SUBSTR(uuid, 11))\n )\n FROM groups\n WHERE deleted_at IS NOT NULL\n);\n\nSELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th\n# ********************************************************************\nSELECT * FROM crm_configurations where provider = 'hubspot';\nSELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133\nSELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null\n# ********************************************************************\n\nselect * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';\nselect\n cp.*\n# DISTINCT t.id\n# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields\nFROM crm_profiles cp\nJOIN crm_configurations crm on crm.id = cp.crm_configuration_id\nJOIN users u on u.id = cp.user_id\nJOIN teams t ON t.id = crm.team_id\nWHERE crm.provider = 'salesforce' and t.status = 'active'\n and cp.archived_at IS NULL and u.deleted_at IS NULL\n and t.id NOT IN (1093)\n and t.id = 2\n and cp.contact_fields IS NULL;\n# and c.crm_provider_id = '003Uu00000ojD4NIAU';\n\nSELECT * FROM users WHERE id = 26484;\nSELECT * FROM crm_profiles WHERE user_id = 26484;\nSELECT * FROM social_accounts WHERE sociable_id = 26484;\nSELECT * FROM crm_configurations where provider = 'salesforce';\nselect * from users where id IN (10022, 10403);\nselect * from users where team_id IN (526);\nselect * from teams where id IN (526, 532);\nselect * from crm_configurations where id IN (500, 516);\nselect * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);\nselect * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 526 and sa.provider = 'salesforce';\nselect * from team_settings where team_id IN (526, 532);\n\nselect * from users where id IN (22824);\nselect * from crm_profiles where crm_configuration_id IN (1026);\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1093 and sa.provider = 'salesforce';\n\nselect * from teams where id = 1099;\nselect * from users where id = 29643\n\nselect * from activity_processing_states;\n\nSELECT * FROM teams where name LIKE '%Fare%'; # 233\nSELECT * FROM opportunities where crm_configuration_id = 215\n# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'\n;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1088 and sa.provider = 'hubspot';\n\nSELECT * FROM teams order by updated_at DESC\nSELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account\n\nselect * from crm_configurations where provider = 'pipedrive';\n\nselect * from teams where id = 957;\nselect * from crm_configurations where id = 957;\n\nSELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743\nSELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;\n\nselect * from users where team_id = 1; # 26726 - Gabriela Dureva\nSELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific\nselect * from activities where user_id = 26726 order by id desc;\nselect * from contacts where crm_configuration_id = 1\nand email IN ('charlotte.ward@prolific.com', 'frankie.bryant@prolific.com'); # 2094416, 2093620\nSELECT * FROM contacts WHERE id = 6284931;\n\nSELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id\nWHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;\n\nselect * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);\nselect * from crm_configurations where id = 1;\n\n43801692-1aeb-32ce-acba-5b80a479701a\n44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b\n405975c0-b3d0-7aaa-821f-09d59cae6dd1\n4caf848d-4bed-2299-b248-7788d41f9fca\n49bedc3f-f196-eef3-89c3-dea6a3b4aa63\n43420989-a09d-b8f8-9806-c8bbf7a02aac\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nSELECT * FROM activities WHERE id = 75461988;\n\nSELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;\n\nselect * from contacts where id = 17900517;\n\nselect * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id\nwhere crm.provider != 'salesforce';\n\nselect * from users where id = 21047;\nSELECT * FROM crm_configurations WHERE id = 892;\nSELECT * FROM teams WHERE id = 942;\nselect * from opportunities where team_id = 942 order by updated_at desc;\nselect * from contacts where team_id = 942 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 942 and sa.provider = 'hubspot';\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430\nSELECT * FROM crm_configurations WHERE id = 1;\nSELECT * FROM teams WHERE crm_id = 1;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nselect id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1\nSELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430\n\nselect * from teams where id = 852;\nselect * from groups where id = 2286;\nselect * from sidekick_settings where team_id = 852;\nselect * from default_activity_types where team_id = 852;\n\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1 AND u.deleted_at IS NULL\nAND u.crm_required = 1\nAND u.team_id = 1\nORDER BY u.team_id;\n\nSELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (\n18481\n );\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1\n AND u.deleted_at IS NULL\n AND u.crm_required = 1\n# AND u.team_id = 1\n AND p.id IS NULL -- Move this condition to WHERE clause\nORDER BY u.team_id;\n\nSELECT * FROM opportunities WHERE id = 20002609;\nselect * from teams where id = 1122; # Velatir, 29953 - christian@velatir.com\nselect * from crm_configurations where id = 1060;\nselect * from crm_layouts where crm_configuration_id = 1060;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1122 and sa.provider = 'hubspot';\nselect * from opportunities where team_id = 1122 order by updated_at desc;\n\nselect * from crm_field_data where object_type = 'contact';\n\nSELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 248 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS\nSELECT * FROM users where id = 24115;\nSELECT * FROM accounts where id = 4002896;\nSELECT * FROM teams WHERE name LIKE '%adswerve%';\nSELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN (\"0069N000003GIQ9QAO\",\"0061r000019yGP9AAM\",\"0066900001S2KWlAAN\",\"0066900001TDpj2AAD\",\"0066900001b8uEwAAI\",\"0069N000001rQi0QAE\",\"006QF00000KD40mYAD\",\"006QF00000LzpRJYAZ\",\"0069N000002uomtQAA\",\"0069N000002xlMLQAY\",\"0066900001NV6ubAAD\",\"0061r00001HJp45AAD\",\"006QF00000uTlUoYAK\",\"006QF00000v0bZqYAI\");\nSELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203\n\nSELECT u.id, u.email, ac.name, a.* FROM activities a\nJOIN users u ON a.user_id = u.id\nJOIN accounts ac ON a.account_id = ac.id\nWHERE\nuuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or\nuuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or\nuuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;\n\nselect * from users where id = 5825;\nSELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;\n\nselect * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;\n19594, 862\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 862 and sa.provider = 'salesforce';\n\nselect * from automated_reports where id = 36;\nselect ar.frequency, r.*, ar.* from automated_report_results r\njoin automated_reports ar on r.report_id = ar.id\nwhere ar.frequency != 'one_off';\n\nselect s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;\nselect * from nudges n where n.activity_search_id\n\nselect * from teams where created_at > '2026-03-09';\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;\n\nselect * from users where team_id = 1 and name like '%Lukas%'; # 7160\n\nSELECT * FROM teams WHERE id = 575;\nselect * from opportunities where team_id = 575;\nSELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,\nselect * from opportunities where team_id = 1126;\nSELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,\nselect * from opportunities where team_id = 1125;\nselect * from contacts c\nwhere c.team_id = 882;\n\nSELECT * FROM activities WHERE id = 76822967;\nSELECT * FROM crm_profiles WHERE user_id = 15440;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 555;\nSELECT * FROM crm_configurations WHERE id = 555;\nSELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 581 and sa.provider = 'salesforce';\n\nSELECT * FROM automated_report_results order by id desc;\n\nselect * from features;\nselect * from team_features where feature_id = 40;\n\nselect * from teams where id = 556;\n\nselect * from automated_reports;\nwhere id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , [\"pdf\",\"podcast\"]\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\nselect * from automated_report_results order by id desc;\nSELECT * FROM automated_report_results WHERE id = 1919;\n\nselect * from automated_report_results WHERE report_id = 54;\n\nselect * from opportunities where id = 7594349;\n\nSELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - jiminnyintegration@lesmills.com\nselect * from playbooks where team_id = 711; # event 226147\nSELECT * FROM playbook_categories WHERE playbook_id = 5515;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';\nSELECT * FROM crm_fields WHERE id = 226147;\nSELECT * FROM crm_field_values WHERE crm_field_id = 226147;\n\nSELECT * FROM crm_configurations WHERE id = 692;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 711 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;\n\nselect * from leads;\n\nselect * from calendars;\n\nSELECT\n t.id AS team_id,\n t.name,\n LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain\nFROM teams t\nJOIN users u ON u.team_id = t.id\nJOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'\nLEFT JOIN team_domains td\n ON td.team_id = t.id\n AND td.deleted_at IS NULL\n AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))\nGROUP BY t.id, t.name, calendar_domain\nORDER BY t.name, calendar_domain;\n\nselect * from users u join calendars c on c.user_id = u.id\nwhere u.team_id = 882;\n\n\nselect * from activities where id = 74049485; # team 563 crm 537\nselect * from activities where id = 73272382; # team 563 crm 537\nselect * from activities where id = 64400389; # team 563 crm 537\nselect * from activities where id = 58081273; # team 563 crm 537\nselect * from activities where id = 54520297; # team 563 crm 537\nselect * from participants where activity_id = 58081273;\n\nselect * from activities where crm_configuration_id = 537 and provider = 'aircall'\nand account_id = 19003658 order by updated_at desc;\n\nselect * from contacts where crm_configuration_id = 537 and id = 35957759;\nselect * from accounts where crm_configuration_id = 537 and id = 19003658;\n\nselect * from automated_report_results where id = 1976;\nselect * from automated_reports where id = 583;\nselect * from activity_searches where id = 87714;\nselect * from activity_search_filters where activity_search_id = 87714;\n\nSELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid\nor uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot';\nselect * from rate_limits;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2\nand id IN (18, 1872);\nselect * from automated_reports where id = 54;\nSELECT * FROM users WHERE id IN (24623,29443,29613);\n\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\n\nselect * from text_relays where created_at > '2026-05-01';\nand id IN (32415, 32416);\n# and id = 32412;\n\nselect * from users where team_id = 2 and email like '%scott%' and id = 29510;\n\nSELECT * FROM activities WHERE uuid_to_bin('67cebfc2-ed56-44a2-8c68-7a0286ed8618') = uuid; # 79763436\n\nSELECT email_provider_id, COUNT(*) as count, GROUP_CONCAT(id) as ids, GROUP_CONCAT(status) as statuses\nFROM text_relays\nWHERE email_provider_id IN ('19e2027868a64b42', '19e2033ed8ea6b10')\nGROUP BY email_provider_id;\nSELECT id, status, telephony_provider_id, created_at\nFROM activities\nWHERE id IN (80028719, 80028846);\nSELECT id, status, code, email_sent_at, created_at, updated_at\nFROM text_relays\nWHERE id IN (32415, 32416);\nSELECT id, status, code, sender, recipient, created_at\nFROM text_relays\nWHERE sender LIKE '%mario.georgiev%' OR sender LIKE '%stoyan.tomov%'\nORDER BY created_at DESC\nLIMIT 10;\n\nSELECT id, uuid, status, code, sender, recipient, created_at, updated_at\nFROM text_relays\nWHERE uuid = uuid_to_bin('0626141c-27a6-4d8c-aff8-7c8020a2c656');\n\n# ***************\nSELECT DISTINCT u.id, u.email, u.name, u.softphone_number, COUNT(a.id) as sms_count\nFROM users u\nINNER JOIN activities a ON u.id = .user_id\nWHERE a.type LIKE 'sms%'\nAND a.created_at > DATE_SUB(NOW(), INTERVAL 30 DAY)\nGROUP BY u.id, u.email, u.name, u.softphone_number\nORDER BY sms_count DESC;\n\nselect * from teams where id = 1;\n\nselect * from roles;\n\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1117 and sa.provider = 'hubspot';\nSELECT * FROM activities WHERE uuid_to_bin('8024fffb-2df7-4017-91f4-d9f896050248') = uuid; # 79933459 YES\nSELECT * FROM activities WHERE uuid_to_bin('25529043-8094-4781-927f-4f4da2a8185c') = uuid; # 80186192 NO\nSELECT * FROM crm_configurations WHERE id = 1053;\nSELECT * FROM teams WHERE id = 1117;\nselect * from users where id = 30249;\nselect * from playbooks where id = 5473;\nselect * from playbook_categories where id = 43783;\nselect * from playbook_categories where playbook_id = 5473;\nselect * from crm_fields where id = 659242;\nselect * from crm_field_values where crm_field_id = 659242;\n\nSELECT * FROM crm_field_data fd\n# JOIN crm_fields f ON fd.crm_field_id = f.id\n# JOIN activities a ON fd.activity_id = a.id\nWHERE activity_id = 79933459\n# AND f.crm_provider_id = 'hs_activity_type';\n\n\nSELECT * FROM activity_messages;\nselect * from text_relays where created_at > '2026-05-01';\nselect * from activities where user_id IN (7160, 18608) and created_at > '2026-05-22' order by id desc;\nselect * from users where team_id = 1 and id IN (18608, 13934, 7160);\nselect * from activities where user_id = 7160 order by id desc limit 10;\n\nselect * from accounts where team_id = 1 and name = 'Column5';\n\nselect * from users where name like '%Subra%'; # 31054, 1117\nselect * from teams where id = 1117;\nselect * from activity_searches where user_id = 31054;\nselect * from activity_search_filters where activity_search_id IN (88882, 88902);","depth":4,"on_screen":true,"value":"SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993\nSELECT * FROM users WHERE id = 25061;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 994;\nSELECT * FROM crm_profiles WHERE user_id = 25061;\n\nselect * from crm_configurations where id = 834;\nSELECT * FROM teams WHERE id = 882;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;\n\nSELECT * FROM contacts where crm_configuration_id = 834;\nSELECT * FROM opportunities WHERE team_id = 933\n# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');\nAND id IN (8482561,18352941,19042734,19232139,19445140,19472541);\nSELECT * FROM opportunity_contacts\nWHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 485; #\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nselect crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id\nwhere crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')\n# and l.converted_at IS NOT NULL\n;\n\n# ********************************************************************\nSELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')\nand opportunity_id IS NULL\norder by id desc;\n\nSELECT * FROM teams WHERE id = 604; # 598\nSELECT * FROM activities WHERE id = 74410828; # chelseaw@allvoices.co\nSELECT * FROM accounts WHERE id = 20068382;\nSELECT * FROM accounts WHERE id = 35186038;\n\nSELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 559 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;\nselect * from sidekick_settings where team_id = 781;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100\n\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 711;\nSELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL\nand is_internal = 0 and status = 'completed'\norder by id desc;\n\nSELECT * FROM crm_layout_entities\nWHERE crm_layout_id IN (2352, 2353);\n;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 556 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;\nSELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;\nselect * from contacts\nwhere crm_configuration_id = 530\nand crm_provider_id = 872252;\n\nselect * from activities where crm_configuration_id = 530\nand user_id = 14343 and type like '%softphone%'\nand created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);\n\n\nSELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t\nJOIN crm_configurations c ON t.id = c.team_id\nWHERE t.status = 'active';\n\nSELECT * FROM teams where id = 1091;\nSELECT * FROM crm_configurations where team_id = 1091;\nSELECT * FROM activity_providers where team_id = 1091;\nSELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT * FROM teams WHERE name LIKE '%Leadventure%';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1091 and sa.provider = 'salesforce';\n\nSELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812\nSELECT * FROM teams where id = 862;\nSELECT * FROM crm_configurations where team_id = 862;\nSELECT * FROM activity_providers where team_id = 862;\nSELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT t.id, crm.id, crm.provider, ap.* FROM teams t\njoin crm_configurations crm on t.id = crm.team_id\njoin activity_providers ap on t.id = ap.team_id\nwhere t.status = 'active' and ap.is_enabled = 1\nand crm.provider = 'hubspot'\nand ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',\n 'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');\n\nSELECT * FROM teams where id = 1068;\nSELECT * FROM crm_configurations where team_id = 1068;\nSELECT * FROM activity_providers where team_id = 1068;\n\nSELECT * FROM activities a\nwhere crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')\nand a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'\n )\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by a.id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1068 and sa.provider = 'hubspot';\n\n# ********************************************************************\n# ********************************************************************\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262\nSELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\nselect * from crm_layouts where crm_configuration_id = 834;\nselect * from crm_layout_entities where crm_layout_id = 2780;\nselect * from crm_fields where id IN (321153,321192,321193,321194);\n\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1057 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8\n\nSELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20\n\nSELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10\n\nSELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #\n\nSELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;\nselect * from users where team_id = 51; # 7783\nSELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130\nselect * from activity_searches where user_id = 7783;\nselect * from activity_search_filters where activity_search_id IN (32291, 32292);\n\nSELECT asf.activity_search_id, asf.id, asf.value\nFROM activity_search_filters asf\nWHERE asf.filter = 'group_id'\nAND asf.value IN (\n SELECT CONCAT(\n HEX(SUBSTR(uuid, 5, 4)), '-',\n HEX(SUBSTR(uuid, 3, 2)), '-',\n HEX(SUBSTR(uuid, 1, 2)), '-',\n HEX(SUBSTR(uuid, 9, 2)), '-',\n HEX(SUBSTR(uuid, 11))\n )\n FROM groups\n WHERE deleted_at IS NOT NULL\n);\n\nSELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th\n# ********************************************************************\nSELECT * FROM crm_configurations where provider = 'hubspot';\nSELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133\nSELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null\n# ********************************************************************\n\nselect * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';\nselect\n cp.*\n# DISTINCT t.id\n# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields\nFROM crm_profiles cp\nJOIN crm_configurations crm on crm.id = cp.crm_configuration_id\nJOIN users u on u.id = cp.user_id\nJOIN teams t ON t.id = crm.team_id\nWHERE crm.provider = 'salesforce' and t.status = 'active'\n and cp.archived_at IS NULL and u.deleted_at IS NULL\n and t.id NOT IN (1093)\n and t.id = 2\n and cp.contact_fields IS NULL;\n# and c.crm_provider_id = '003Uu00000ojD4NIAU';\n\nSELECT * FROM users WHERE id = 26484;\nSELECT * FROM crm_profiles WHERE user_id = 26484;\nSELECT * FROM social_accounts WHERE sociable_id = 26484;\nSELECT * FROM crm_configurations where provider = 'salesforce';\nselect * from users where id IN (10022, 10403);\nselect * from users where team_id IN (526);\nselect * from teams where id IN (526, 532);\nselect * from crm_configurations where id IN (500, 516);\nselect * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);\nselect * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 526 and sa.provider = 'salesforce';\nselect * from team_settings where team_id IN (526, 532);\n\nselect * from users where id IN (22824);\nselect * from crm_profiles where crm_configuration_id IN (1026);\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1093 and sa.provider = 'salesforce';\n\nselect * from teams where id = 1099;\nselect * from users where id = 29643\n\nselect * from activity_processing_states;\n\nSELECT * FROM teams where name LIKE '%Fare%'; # 233\nSELECT * FROM opportunities where crm_configuration_id = 215\n# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'\n;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1088 and sa.provider = 'hubspot';\n\nSELECT * FROM teams order by updated_at DESC\nSELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account\n\nselect * from crm_configurations where provider = 'pipedrive';\n\nselect * from teams where id = 957;\nselect * from crm_configurations where id = 957;\n\nSELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743\nSELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;\n\nselect * from users where team_id = 1; # 26726 - Gabriela Dureva\nSELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific\nselect * from activities where user_id = 26726 order by id desc;\nselect * from contacts where crm_configuration_id = 1\nand email IN ('charlotte.ward@prolific.com', 'frankie.bryant@prolific.com'); # 2094416, 2093620\nSELECT * FROM contacts WHERE id = 6284931;\n\nSELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id\nWHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;\n\nselect * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);\nselect * from crm_configurations where id = 1;\n\n43801692-1aeb-32ce-acba-5b80a479701a\n44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b\n405975c0-b3d0-7aaa-821f-09d59cae6dd1\n4caf848d-4bed-2299-b248-7788d41f9fca\n49bedc3f-f196-eef3-89c3-dea6a3b4aa63\n43420989-a09d-b8f8-9806-c8bbf7a02aac\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nSELECT * FROM activities WHERE id = 75461988;\n\nSELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;\n\nselect * from contacts where id = 17900517;\n\nselect * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id\nwhere crm.provider != 'salesforce';\n\nselect * from users where id = 21047;\nSELECT * FROM crm_configurations WHERE id = 892;\nSELECT * FROM teams WHERE id = 942;\nselect * from opportunities where team_id = 942 order by updated_at desc;\nselect * from contacts where team_id = 942 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 942 and sa.provider = 'hubspot';\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430\nSELECT * FROM crm_configurations WHERE id = 1;\nSELECT * FROM teams WHERE crm_id = 1;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nselect id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1\nSELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430\n\nselect * from teams where id = 852;\nselect * from groups where id = 2286;\nselect * from sidekick_settings where team_id = 852;\nselect * from default_activity_types where team_id = 852;\n\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1 AND u.deleted_at IS NULL\nAND u.crm_required = 1\nAND u.team_id = 1\nORDER BY u.team_id;\n\nSELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (\n18481\n );\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1\n AND u.deleted_at IS NULL\n AND u.crm_required = 1\n# AND u.team_id = 1\n AND p.id IS NULL -- Move this condition to WHERE clause\nORDER BY u.team_id;\n\nSELECT * FROM opportunities WHERE id = 20002609;\nselect * from teams where id = 1122; # Velatir, 29953 - christian@velatir.com\nselect * from crm_configurations where id = 1060;\nselect * from crm_layouts where crm_configuration_id = 1060;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1122 and sa.provider = 'hubspot';\nselect * from opportunities where team_id = 1122 order by updated_at desc;\n\nselect * from crm_field_data where object_type = 'contact';\n\nSELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 248 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS\nSELECT * FROM users where id = 24115;\nSELECT * FROM accounts where id = 4002896;\nSELECT * FROM teams WHERE name LIKE '%adswerve%';\nSELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN (\"0069N000003GIQ9QAO\",\"0061r000019yGP9AAM\",\"0066900001S2KWlAAN\",\"0066900001TDpj2AAD\",\"0066900001b8uEwAAI\",\"0069N000001rQi0QAE\",\"006QF00000KD40mYAD\",\"006QF00000LzpRJYAZ\",\"0069N000002uomtQAA\",\"0069N000002xlMLQAY\",\"0066900001NV6ubAAD\",\"0061r00001HJp45AAD\",\"006QF00000uTlUoYAK\",\"006QF00000v0bZqYAI\");\nSELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203\n\nSELECT u.id, u.email, ac.name, a.* FROM activities a\nJOIN users u ON a.user_id = u.id\nJOIN accounts ac ON a.account_id = ac.id\nWHERE\nuuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or\nuuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or\nuuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;\n\nselect * from users where id = 5825;\nSELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;\n\nselect * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;\n19594, 862\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 862 and sa.provider = 'salesforce';\n\nselect * from automated_reports where id = 36;\nselect ar.frequency, r.*, ar.* from automated_report_results r\njoin automated_reports ar on r.report_id = ar.id\nwhere ar.frequency != 'one_off';\n\nselect s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;\nselect * from nudges n where n.activity_search_id\n\nselect * from teams where created_at > '2026-03-09';\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;\n\nselect * from users where team_id = 1 and name like '%Lukas%'; # 7160\n\nSELECT * FROM teams WHERE id = 575;\nselect * from opportunities where team_id = 575;\nSELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,\nselect * from opportunities where team_id = 1126;\nSELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,\nselect * from opportunities where team_id = 1125;\nselect * from contacts c\nwhere c.team_id = 882;\n\nSELECT * FROM activities WHERE id = 76822967;\nSELECT * FROM crm_profiles WHERE user_id = 15440;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 555;\nSELECT * FROM crm_configurations WHERE id = 555;\nSELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 581 and sa.provider = 'salesforce';\n\nSELECT * FROM automated_report_results order by id desc;\n\nselect * from features;\nselect * from team_features where feature_id = 40;\n\nselect * from teams where id = 556;\n\nselect * from automated_reports;\nwhere id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , [\"pdf\",\"podcast\"]\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\nselect * from automated_report_results order by id desc;\nSELECT * FROM automated_report_results WHERE id = 1919;\n\nselect * from automated_report_results WHERE report_id = 54;\n\nselect * from opportunities where id = 7594349;\n\nSELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - jiminnyintegration@lesmills.com\nselect * from playbooks where team_id = 711; # event 226147\nSELECT * FROM playbook_categories WHERE playbook_id = 5515;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';\nSELECT * FROM crm_fields WHERE id = 226147;\nSELECT * FROM crm_field_values WHERE crm_field_id = 226147;\n\nSELECT * FROM crm_configurations WHERE id = 692;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 711 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;\n\nselect * from leads;\n\nselect * from calendars;\n\nSELECT\n t.id AS team_id,\n t.name,\n LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain\nFROM teams t\nJOIN users u ON u.team_id = t.id\nJOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'\nLEFT JOIN team_domains td\n ON td.team_id = t.id\n AND td.deleted_at IS NULL\n AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))\nGROUP BY t.id, t.name, calendar_domain\nORDER BY t.name, calendar_domain;\n\nselect * from users u join calendars c on c.user_id = u.id\nwhere u.team_id = 882;\n\n\nselect * from activities where id = 74049485; # team 563 crm 537\nselect * from activities where id = 73272382; # team 563 crm 537\nselect * from activities where id = 64400389; # team 563 crm 537\nselect * from activities where id = 58081273; # team 563 crm 537\nselect * from activities where id = 54520297; # team 563 crm 537\nselect * from participants where activity_id = 58081273;\n\nselect * from activities where crm_configuration_id = 537 and provider = 'aircall'\nand account_id = 19003658 order by updated_at desc;\n\nselect * from contacts where crm_configuration_id = 537 and id = 35957759;\nselect * from accounts where crm_configuration_id = 537 and id = 19003658;\n\nselect * from automated_report_results where id = 1976;\nselect * from automated_reports where id = 583;\nselect * from activity_searches where id = 87714;\nselect * from activity_search_filters where activity_search_id = 87714;\n\nSELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid\nor uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot';\nselect * from rate_limits;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2\nand id IN (18, 1872);\nselect * from automated_reports where id = 54;\nSELECT * FROM users WHERE id IN (24623,29443,29613);\n\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\n\nselect * from text_relays where created_at > '2026-05-01';\nand id IN (32415, 32416);\n# and id = 32412;\n\nselect * from users where team_id = 2 and email like '%scott%' and id = 29510;\n\nSELECT * FROM activities WHERE uuid_to_bin('67cebfc2-ed56-44a2-8c68-7a0286ed8618') = uuid; # 79763436\n\nSELECT email_provider_id, COUNT(*) as count, GROUP_CONCAT(id) as ids, GROUP_CONCAT(status) as statuses\nFROM text_relays\nWHERE email_provider_id IN ('19e2027868a64b42', '19e2033ed8ea6b10')\nGROUP BY email_provider_id;\nSELECT id, status, telephony_provider_id, created_at\nFROM activities\nWHERE id IN (80028719, 80028846);\nSELECT id, status, code, email_sent_at, created_at, updated_at\nFROM text_relays\nWHERE id IN (32415, 32416);\nSELECT id, status, code, sender, recipient, created_at\nFROM text_relays\nWHERE sender LIKE '%mario.georgiev%' OR sender LIKE '%stoyan.tomov%'\nORDER BY created_at DESC\nLIMIT 10;\n\nSELECT id, uuid, status, code, sender, recipient, created_at, updated_at\nFROM text_relays\nWHERE uuid = uuid_to_bin('0626141c-27a6-4d8c-aff8-7c8020a2c656');\n\n# ***************\nSELECT DISTINCT u.id, u.email, u.name, u.softphone_number, COUNT(a.id) as sms_count\nFROM users u\nINNER JOIN activities a ON u.id = .user_id\nWHERE a.type LIKE 'sms%'\nAND a.created_at > DATE_SUB(NOW(), INTERVAL 30 DAY)\nGROUP BY u.id, u.email, u.name, u.softphone_number\nORDER BY sms_count DESC;\n\nselect * from teams where id = 1;\n\nselect * from roles;\n\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1117 and sa.provider = 'hubspot';\nSELECT * FROM activities WHERE uuid_to_bin('8024fffb-2df7-4017-91f4-d9f896050248') = uuid; # 79933459 YES\nSELECT * FROM activities WHERE uuid_to_bin('25529043-8094-4781-927f-4f4da2a8185c') = uuid; # 80186192 NO\nSELECT * FROM crm_configurations WHERE id = 1053;\nSELECT * FROM teams WHERE id = 1117;\nselect * from users where id = 30249;\nselect * from playbooks where id = 5473;\nselect * from playbook_categories where id = 43783;\nselect * from playbook_categories where playbook_id = 5473;\nselect * from crm_fields where id = 659242;\nselect * from crm_field_values where crm_field_id = 659242;\n\nSELECT * FROM crm_field_data fd\n# JOIN crm_fields f ON fd.crm_field_id = f.id\n# JOIN activities a ON fd.activity_id = a.id\nWHERE activity_id = 79933459\n# AND f.crm_provider_id = 'hs_activity_type';\n\n\nSELECT * FROM activity_messages;\nselect * from text_relays where created_at > '2026-05-01';\nselect * from activities where user_id IN (7160, 18608) and created_at > '2026-05-22' order by id desc;\nselect * from users where team_id = 1 and id IN (18608, 13934, 7160);\nselect * from activities where user_id = 7160 order by id desc limit 10;\n\nselect * from accounts where team_id = 1 and name = 'Column5';\n\nselect * from users where name like '%Subra%'; # 31054, 1117\nselect * from teams where id = 1117;\nselect * from activity_searches where user_id = 31054;\nselect * from activity_search_filters where activity_search_id IN (88882, 88902);","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-3264450658369633090
|
1136716483744153188
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
#12121 on JY-20963-fix-im Project: faVsco.js, menu
#12121 on JY-20963-fix-import-on-deleted-entity, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
2
69
3
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Hubspot;
use HubSpot\Client\Crm\Deals\ApiException as DealApiException;
use HubSpot\Client\Crm\Contacts\ApiException as ContactApiException;
use HubSpot\Client\Crm\Companies\ApiException as CompanyApiException;
use HubSpot\Client\Crm\Contacts\Model\SimplePublicObjectWithAssociations as ContactsWithAssociations;
use HubSpot\Client\Crm\Companies\Model\SimplePublicObjectWithAssociations as CompaniesWithAssociations;
use HubSpot\Client\Crm\Deals\Model\SimplePublicObjectWithAssociations as DealWithAssociations;
use HubSpot\Client\Crm\Objects\Model\SimplePublicObjectInput;
use HubSpot\Client\Crm\Objects\Model\SimplePublicObjectWithAssociations as ObjectWithAssociations;
use HubSpot\Client\Crm\Pipelines\Model\Error;
use HubSpot\Client\Crm\Pipelines\Model\PipelineStage;
use HubSpot\Client\Crm\Properties\Model\Property;
use HubSpot\Discovery\Discovery;
use Jiminny\Exceptions\CrmException;
use Jiminny\Exceptions\RateLimitException;
use Jiminny\Exceptions\SocialAccountTokenInvalidException;
use Jiminny\Jobs\Crm\NoteObject;
use Jiminny\Models\Crm\Field;
use Jiminny\Services\Crm\BaseClient;
use Jiminny\Services\Crm\Hubspot\DTO\Response\Owner;
use Jiminny\Services\SocialAccountService;
use SevenShores\Hubspot\Exceptions\BadRequest;
use SevenShores\Hubspot\Exceptions\HubspotException;
use SevenShores\Hubspot\Factory;
use SevenShores\Hubspot\Http\Response;
use Jiminny\Services\Crm\Hubspot\Pagination\HubspotPaginationService;
use Illuminate\Support\Facades\Redis;
use Throwable;
/**
* @phpstan-type CrmFieldOption array{id:string, label:string, value?:string}
*/
class Client extends BaseClient implements HubspotClientInterface
{
public const string MIN_API_VERSION = '2';
public const string BASE_URL = '[URL_WITH_CREDENTIALS] T
*
* @param callable(): T $apiCall The API call to execute
*
* @throws RateLimitException When rate limit is hit or cached rate limit is active
*
* @return T The result of the API call
*/
private function executeRequest(callable $apiCall)
{
$cacheKey = $this->getRateLimitCacheKey();
$cachedExpiresAt = Redis::get($cacheKey);
if (is_string($cachedExpiresAt) && is_numeric($cachedExpiresAt)) {
$remaining = max(1, (int) $cachedExpiresAt - time());
throw new RateLimitException(
'Hubspot rate limit (cached circuit-breaker)',
$remaining,
);
}
try {
return $apiCall();
} catch (Throwable $e) {
if ($this->isHubspotRateLimit($e)) {
$retryAfter = $this->parseRetryAfter($e);
// NX: only the first job to receive a 429 in this burst sets the key.
// Subsequent 429s in the same burst leave the TTL untouched so the
// window is not reset by every concurrent job hitting the limit.
Redis::set($cacheKey, (string) (time() + $retryAfter), 'EX', $retryAfter, 'NX');
$this->log->warning('[Hubspot] Received 429 from API', [
'team_id' => $this->config->team_id,
'config_id' => $this->config->getId(),
'retry_after' => $retryAfter,
'reason' => $e->getMessage(),
]);
throw new RateLimitException('Hubspot returned 429', $retryAfter, $e);
}
throw $e;
}
}
private function getRateLimitCacheKey(): string
{
return sprintf('hubspot:ratelimit:config:%d', $this->config->getId());
}
private function isHubspotRateLimit(Throwable $e): bool
{
if ($e instanceof BadRequest
|| $e instanceof DealApiException
|| $e instanceof ContactApiException
|| $e instanceof CompanyApiException
|| $e instanceof \GuzzleHttp\Exception\RequestException
) {
return (int) $e->getCode() === 429;
}
return false;
}
private function parseRetryAfter(Throwable $e): int
{
if (method_exists($e, 'getResponseHeaders')) {
$headers = $e->getResponseHeaders() ?: [];
$value = $headers['Retry-After'] ?? $headers['retry-after'] ?? null;
if (is_array($value)) {
$value = $value[0] ?? null;
}
if (is_numeric($value)) {
return (int) $value;
}
}
$message = strtolower($e->getMessage());
if (str_contains($message, 'daily')) {
return 600;
}
if (str_contains($message, 'ten secondly')) {
return 10;
}
if (str_contains($message, 'secondly')) {
return 1;
}
$this->log->warning('[Hubspot] No retry-after header or known message, using default', [
'exception_class' => get_class($e),
'message' => $message,
]);
return 10;
}
public function getMinimumApiVersion(): string
{
return self::MIN_API_VERSION;
}
public function getInstance(): Factory
{
return new Factory([
'key' => $this->accessToken,
'oauth2' => true,
'base_url' => $this->baseUrl,
]);
}
public function getNewInstance(): Discovery
{
return \HubSpot\Factory::createWithAccessToken($this->accessToken);
}
/**
* Secondly and daily limits for Hubspot API
*
* Product Tier: Free & Starter | Professional & Enterprise | API add-on (any tier)
* Burst: 100/10 seconds | 150/10 seconds | 200/10 seconds
* Daily: 250,000 | 500,000 | 1,000,000
*
* Official documentation states: The search endpoints are rate limited to five requests per second.
* Since with 5 RPS were still hitting secondly rate limits we lowered it to 4
*/
public function getPaginatedData(array $payload, string $type, int $offset = 0): array
{
$total = 0;
$lastId = null;
$rows = [];
foreach ($this->getPaginatedDataGenerator($payload, $type, $offset, $total, $lastId) as $row) {
$rows[] = $row;
}
return ['results' => $rows, 'total' => $total, 'last_record' => $lastId];
}
/**
* @throws HubspotException
* @throws SocialAccountTokenInvalidException
* @throws BadRequest
*/
public function getPaginatedDataGenerator(
array $payload,
string $type,
int $offset = 0,
int &$total = 0,
?string &$lastRecordId = null
): \Generator {
return $this->paginationService->getPaginatedDataGenerator(
$this,
$payload,
$type,
$offset,
$total,
$lastRecordId
);
}
/**
* Execute a search request against HubSpot CRM objects with rate limiting.
*
* @param string $objectType The object type ('deals', 'companies', 'contacts', 'calls')
* @param array<string, mixed> $payload The search payload with filters, sorts, properties, etc.
*
* @throws RateLimitException When rate limit is hit
* @throws HubspotException On API errors
*
* @return array The search response with 'results', 'total', 'paging' keys
*/
public function search(string $objectType, array $payload): array
{
$endpoint = self::BASE_URL . "/crm/v3/objects/{$objectType}/search";
return $this->executeRequest(function () use ($endpoint, $payload) {
$response = $this->getInstance()->getClient()->request('POST', $endpoint, ['json' => $payload]);
return $response->toArray();
});
}
/**
* @throws DealApiException
* @throws CrmException
*/
public function getOpportunityById(string $crmId, array $fields): array
{
try {
$deal = $this->getNewInstance()->crm()->deals()->basicApi()->getById(
$crmId,
implode(',', $fields),
'companies,contacts'
);
} catch (DealApiException $e) {
$this->log->info('[Hubspot] Failed to fetch opportunity', [
'crm_id' => $crmId,
'reason' => $e->getMessage(),
]);
throw $e;
}
if (! $deal instanceof DealWithAssociations) {
throw new CrmException('Deal not found');
}
return [
'id' => $deal->getId(),
'properties' => $deal->getProperties(),
'associations' => $deal->getAssociations(),
];
}
/**
* Generic batch read method for HubSpot objects
*
* @param string $objectType The object type ('deals', 'companies', 'contacts')
* @param array<string> $crmIds Array of HubSpot object IDs (max 100)
* @param array<string> $fields Array of property names to fetch
*
* @return array<string, array> Array keyed by CRM ID with object data
*/
private function batchReadObjects(string $objectType, array $crmIds, array $fields): array
{
if (empty($crmIds)) {
return [];
}
$this->validateBatchSize($objectType, $crmIds);
$this->ensureValidToken();
try {
$batchConfig = $this->createBatchConfiguration($objectType);
$batchReadRequest = $this->prepareBatchRequest($batchConfig, $crmIds, $fields);
$response = $batchConfig['api']->read($batchReadRequest);
$this->validateApiResponse($response, $objectType);
$results = $this->processApiResults($response);
$this->logBatchResults($objectType, $crmIds, $results);
return $results;
} catch (\Throwable $e) {
$this->handleBatchError($e, $objectType, $crmIds);
}
}
private function validateBatchSize(string $objectType, array $crmIds): void
{
if (count($crmIds) > 100) {
throw new \InvalidArgumentException("Batch size cannot exceed 100 {$objectType}");
}
}
private function createBatchConfiguration(string $objectType): array
{
$configurations = [
'deals' => [
'batchReadRequest' => new \HubSpot\Client\Crm\Deals\Model\BatchReadInputSimplePublicObjectId(),
'inputClass' => \HubSpot\Client\Crm\Deals\Model\SimplePublicObjectId::class,
'api' => $this->getNewInstance()->crm()->deals()->batchApi(),
],
'companies' => [
'batchReadRequest' => new \HubSpot\Client\Crm\Companies\Model\BatchReadInputSimplePublicObjectId(),
'inputClass' => \HubSpot\Client\Crm\Companies\Model\SimplePublicObjectId::class,
'api' => $this->getNewInstance()->crm()->companies()->batchApi(),
],
'contacts' => [
'batchReadRequest' => new \HubSpot\Client\Crm\Contacts\Model\BatchReadInputSimplePublicObjectId(),
'inputClass' => \HubSpot\Client\Crm\Contacts\Model\SimplePublicObjectId::class,
'api' => $this->getNewInstance()->crm()->contacts()->batchApi(),
],
];
if (! isset($configurations[$objectType])) {
throw new \InvalidArgumentException("Unsupported object type: {$objectType}");
}
return $configurations[$objectType];
}
private function prepareBatchRequest(array $batchConfig, array $crmIds, array $fields): object
{
$batchReadRequest = $batchConfig['batchReadRequest'];
$inputClass = $batchConfig['inputClass'];
$inputs = array_map(function ($crmId) use ($inputClass) {
$input = new $inputClass();
$input->setId($crmId);
return $input;
}, $crmIds);
$batchReadRequest->setInputs($inputs);
$batchReadRequest->setProperties($fields);
return $batchReadRequest;
}
private function validateApiResponse($response, string $objectType): void
{
if (! $response) {
throw new CrmException("HubSpot API returned null response for {$objectType} batch read");
}
}
private function processApiResults($response): array
{
$results = [];
$responseResults = $response->getResults();
if ($responseResults) {
foreach ($responseResults as $object) {
if ($object && $object->getId()) {
$results[$object->getId()] = [
'id' => $object->getId(),
'properties' => $object->getProperties() ?: [],
];
}
}
}
return $results;
}
private function logBatchResults(string $objectType, array $crmIds, array $results): void
{
$this->log->info("[HubSpot] Batch fetched {$objectType}", [
'requested_count' => count($crmIds),
'returned_count' => count($results),
'crm_ids' => $crmIds,
]);
}
private function handleBatchError(\Throwable $e, string $objectType, array $crmIds): void
{
$errorMessage = $e->getMessage() ?: 'Unknown error';
$errorTrace = $e->getTraceAsString() ?: 'No trace available';
$this->log->error("[HubSpot] Failed to batch fetch {$objectType}", [
'crm_ids' => $crmIds,
'error' => $errorMessage,
'trace' => $errorTrace,
]);
throw new CrmException("Failed to batch fetch {$objectType}: " . $errorMessage);
}
/**
* Batch read multiple opportunities by their CRM IDs
*
* @param array<string> $crmIds Array of HubSpot deal IDs (max 100)
* @param array<string> $fields Array of property names to fetch
*
* @return array<string, array> Array keyed by CRM ID with opportunity data
*/
public function getOpportunitiesByIds(array $crmIds, array $fields): array
{
return $this->batchReadObjects('deals', $crmIds, $fields);
}
/**
* Batch read multiple companies by their CRM IDs
*
* @param array<string> $crmIds Array of HubSpot company IDs (max 100)
* @param array<string> $fields Array of property names to fetch
*
* @return array<string, array> Array keyed by CRM ID with company data
*/
public function getCompaniesByIds(array $crmIds, array $fields): array
{
return $this->batchReadObjects('companies', $crmIds, $fields);
}
/**
* Batch read multiple contacts by their CRM IDs
*
* @param array<string> $crmIds Array of HubSpot contact IDs (max 100)
* @param array<string> $fields Array of property names to fetch
*
* @return array<string, array> Array keyed by CRM ID with contact data
*/
public function getContactsByIds(array $crmIds, array $fields): array
{
return $this->batchReadObjects('contacts', $crmIds, $fields);
}
/**
* @throws CompanyApiException
* @throws CrmException
*/
public function getAccountById(string $crmId, array $fields): array
{
try {
$company = $this->getNewInstance()->crm()->companies()->basicApi()->getById(
$crmId,
implode(',', $fields),
);
} catch (CompanyApiException $e) {
$this->log->info('[Hubspot] Failed to fetch account', [
'crm_id' => $crmId,
'reason' => $e->getMessage(),
]);
throw $e;
}
if (! $company instanceof CompaniesWithAssociations) {
throw new CrmException('Account not found');
}
return [
'id' => $company->getId(),
'properties' => $company->getProperties(),
];
}
/**
* @throws ContactApiException
* @throws CrmException
*/
public function getContactById(string $crmId, array $fields): array
{
try {
$contact = $this->getNewInstance()->crm()->contacts()->basicApi()->getById(
$crmId,
implode(',', $fields)
);
} catch (ContactApiException $e) {
$this->log->info('[Hubspot] Failed to fetch contact', [
'crm_id' => $crmId,
'reason' => $e->getMessage(),
]);
throw $e;
}
if (! $contact instanceof ContactsWithAssociations) {
throw new CrmException('Contact not found');
}
return [
'id' => $contact->getId(),
'properties' => $contact->getProperties(),
];
}
/**
* This is email search request that Hubspot offers as GET (more generous quota)
*/
public function getContactByEmail(string $email, array $fields = []): array
{
try {
$contact = $this->getNewInstance()->crm()->contacts()->basicApi()->getById(
$email,
implode(',', $fields),
null,
false,
'email'
);
return [
'id' => $contact->getId(),
'properties' => $contact->getProperties(),
];
} catch (ContactApiException $e) {
$this->log->info('[Hubspot] Failed to fetch contact', [
'email' => $email,
'reason' => $e->getMessage(),
]);
return [];
}
}
/**
* @throws CrmException
*/
public function fetchProperty(string $objectType, string $propertyId): Property
{
$result = $this->getNewInstance()->crm()->properties()->coreApi()->getByName($objectType, $propertyId);
if (! $result instanceof Property) {
$this->log->error('[Hubspot] Failed to fetch property', [
'object_type' => $objectType,
'property_id' => $propertyId,
'reason' => $result->getMessage(),
]);
throw new CrmException('Failed to fetch property');
}
return $result;
}
/**
* @return array<CrmFieldOption>
*/
public function fetchPropertyOptions(string $objectType, string $propertyId): array
{
/** @var array<CrmFieldOption> */
return $this->fetchProperty($objectType, $propertyId)->getOptions();
}
/**
* @return array<array{id:string, label:string, deleted:bool}>
*/
public function fetchCallDispositions(): array
{
/** @var Response $response */
$response = $this->getInstance()->engagements()->getCallDispositions();
/**
* @var array<array{
* id:string,
* label:string,
* deleted: bool
* }>
*/
return $response->toArray();
}
/**
* @return array<CrmFieldOption>
*/
public function fetchOpportunityPipelineStages(): array
{
$stages = [];
$apiResponse = $this->getNewInstance()->crm()->pipelines()->pipelinesApi()->getAll('deals');
if ($apiResponse instanceof Error) {
$this->log->error('[Hubspot] Failed to fetch opportunity pipelines', [
'reason' => $apiResponse->getMessage(),
]);
return [];
}
foreach ($apiResponse->getResults() as $pipeline) {
$pipelineStages = array_map(
static function (PipelineStage $stage) {
return [
'id' => $stage->getId(),
'label' => $stage->getLabel(),
];
},
$pipeline->getStages()
);
$stages = array_merge($stages, $pipelineStages);
}
return $stages;
}
public function fetchOpportunityPipelines(): array
{
$pipelines = [];
try {
$apiResponse = $this->makeRequest('/crm/v3/pipelines/deals');
} catch (\Exception $e) {
$this->log->info('[Hubspot] Failed to fetch opportunity pipelines', [
'reason' => $e->getMessage(),
]);
return [];
}
$response = $apiResponse->toArray();
foreach ($response['results'] as $pipeline) {
$pipelines[] = [
'id' => $pipeline['id'],
'label' => $pipeline['label'],
];
}
return $pipelines;
}
/**
* @return array<CrmFieldOption>
*/
public function fetchMeetingOutcomeFieldOptions(Field $field): array
{
return $field->getCrmProviderId() === 'meetingOutcome'
? $this->fetchMeetingOutcomeTypes()
: $this->fetchCallActivityTypes();
}
public function fetchMeetingOutcomeTypes(): array
{
return $this->extractMeetingTypeOptions(
'[URL_WITH_CREDENTIALS] Response $response */
$response = $this->getInstance()
->getClient()
->request('GET', $endpoint);
/**
* @var array<array{
* value: string,
* label: string,
* displayOrder: int
* }> $optionData
*/
$optionData = $response->toArray()['options'] ?? [];
$options = [];
foreach ($optionData as $item) {
$options[] = [
'id' => $item['value'],
'value' => $item['value'],
'label' => $item['label'],
'display_order' => $item['displayOrder'],
];
}
return $options;
}
/**
* @return array<CrmFieldOption>
*/
public function fetchDispositionFieldOptions(): array
{
$options = [];
$dispositions = $this->fetchCallDispositions();
foreach ($dispositions as $disposition) {
if ($disposition['deleted'] !== false) {
continue;
}
$option['value'] = $disposition['id'];
$option['id'] = $disposition['id'];
$option['label'] = $disposition['label'];
$options[] = $option;
}
return $options;
}
/**
* @return array<CrmFieldOption>
*/
public function fetchOpportunityFieldOptions(Field $field): array
{
if ($field->isStageField()) {
return $this->fetchOpportunityPipelineStages();
}
if ($field->isPipelineField()) {
return $this->fetchOpportunityPipelines();
}
return $this->fetchPropertyOptions('deals', $field->getCrmProviderId());
}
/**
* @throws BadRequest
* @throws HubspotException
*/
public function makeRequest(string $endpoint, $method = 'GET', $payload = [], ?string $queryString = null)
{
$endpoint = self::BASE_URL . $endpoint;
if ($method === 'GET') {
return $this->getInstance()->getClient()?->request(
method: $method,
endpoint: $endpoint,
query_string: $queryString
);
} else {
return $this->getInstance()->getClient()->request($method, $endpoint, [
'json' => ($payload),
]);
}
}
/**
* @throws BadRequest
* @throws HubspotException
*/
public function createMeeting(array $payload): Response
{
$endpoint = '/crm/v3/objects/meetings';
return $this->makeRequest($endpoint, 'POST', $payload);
}
/**
* @throws BadRequest
* @throws HubspotException
*/
public function updateMeeting(string $meetingId, array $payload): Response
{
$endpoint = '/crm/v3/objects/meetings/' . $meetingId;
return $this->makeRequest($endpoint, 'PATCH', $payload);
}
/**
* @throws \Exception
*/
public function createNote(
string $body,
string $ownerId,
int $timestamp,
string $objectId,
NoteObject $noteObject
): ?string {
try {
$noteInput = new SimplePublicObjectInput([
'properties' => [
'hs_note_body' => $body,
'hubspot_owner_id' => $ownerId,
'hs_timestamp' => $timestamp,
],
]);
// Create note
$note = $this->getNewInstance()->crm()->objects()->basicApi()->create('note', $noteInput);
$this->getNewInstance()->crm()->objects()->associationsApi()->create(
'note',
$note->getId(),
$this->getNoteObject($noteObject),
$objectId,
$this->getNoteAssociationType($noteObject),
);
return $note->getId();
} catch (\Exception $e) {
$this->log->error('[Hubspot] Failed to create note', [
'objectId' => $objectId,
'noteObject' => $noteObject->getObjectType(),
'reason' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return null;
}
public function updateEngagement(string $objectId, array $engagement, array $metadata): void
{
$this->getInstance()->engagements()->update($objectId, $engagement, $metadata);
}
public function getEngagementData(string $engagementId): array
{
$engagement = $this->getInstance()->engagements()->get($engagementId);
return $engagement->toArray();
}
public function createEngagement(array $engagement, array $associations, array $metadata): Response
{
return $this->getInstance()
->engagements()
->create($engagement, $associations, $metadata);
}
public function isUnauthorizedException(\Exception $e): bool
{
// Check for specific HubSpot API exception types first
if ($e instanceof BadRequest) {
// BadRequest can contain 401 status codes
return $e->getCode() === 401;
}
// Check for HTTP client exceptions with status codes
if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
$response = $e->getResponse();
if ($response !== null) {
return $response->getStatusCode() === 401;
}
}
// Check for Guzzle HTTP exceptions
if ($e instanceof \GuzzleHttp\Exception\ClientException) {
return $e->getCode() === 401;
}
// Fallback to string matching as last resort, but be more specific
$message = strtolower($e->getMessage());
return str_contains($message, '401 unauthorized') ||
str_contains($message, 'http 401') ||
str_contains($message, 'status code 401') ||
(preg_match('/\b401\b/', $message) && str_contains($message, 'unauthorized'));
}
/**
* Validates and refreshes the access token if needed before API requests.
* This ensures long-running processes don't fail due to token expiration.
*
* @throws SocialAccountTokenInvalidException
*/
public function ensureValidToken(): void
{
if ($this->oauthAccount === null) {
return;
}
$newToken = $this->tokenManager->ensureValidToken($this->oauthAccount);
if ($newToken !== null) {
$this->accessToken = $newToken;
}
}
public function getConfig()
{
return $this->config;
}
// returns only active (archived=false)
public function getOwners(): array
{
return $this->getNewInstance()->crm()->owners()->getAll();
}
/**
* @param bool $archived
*
* @return array<Owner>|[]
*/
public function getOwnersArchived(bool $archived = true): array
{
$endpoint = '/crm/v3/owners';
$queryParams = [
'archived' => $archived ? 'true' : 'false',
];
$queryString = http_build_query($queryParams);
$owners = [];
try {
$response = $this->makeRequest(endpoint: $endpoint, queryString: $queryString);
$responseData = $response?->toArray();
foreach ($responseData['results'] as $result) {
try {
$owners[] = Owner::create($result);
} catch (Throwable $e) {
$this->log->error('[HubSpot] Failed to process owner data', [
'result' => $result,
'error' => $e->getMessage(),
]);
continue;
}
}
} catch (Throwable $e) {
$this->log->error('HubSpot] Failed to fetch owners', [
'archived' => $archived,
'error' => $e->getMessage(),
]);
return [];
}
return $owners;
}
public function getMeeting(string $engagementId): ObjectWithAssociations
{
return $this->getNewInstance()->crm()->objects()->basicApi()
->getById('meeting', $engagementId, null, 'contact,company,deal');
}
public function deleteEngagement(string $engagementId): void
{
$this->getInstance()->engagements()->delete((int) $engagementId);
}
public function getAssociationsData(array $ids, string $fromObject, string $toObject): array
{
$associationData = [];
$idChunks = array_chunk($ids, self::ASSOCIATIONS_BATCH_SIZE_LIMIT);
foreach ($idChunks as $idChunk) {
try {
$batchInput = new \HubSpot\Client\Crm\Associations\Model\BatchInputPublicObjectId();
$batchInput->setInputs(array_map(function ($id) {
$publicObjectId = new \HubSpot\Client\Crm\Associations\Model\PublicObjectId();
$publicObjectId->setId($id);
return $publicObjectId;
}, $idChunk));
$associatedObjectsData = $this
->getNewInstance()
->crm()
->associations()
->batchApi()
->read($fromObject, $toObject, $batchInput);
if ($associatedObjectsData instanceof \HubSpot\Client\Crm\Associations\Model\BatchResponsePublicAssociationMulti) {
foreach ($associatedObjectsData->getResults() as $association) {
$from = $association->getFrom()->getId();
$toAssociations = $association->getTo();
if (! empty($toAssociations)) {
$associationData[$from] = array_map(function ($item) {
return $item->getId();
}, $toAssociations);
}
}
}
} catch (\Exception $e) {
$this->log->error('[Hubspot] Failed to fetch associations', [
'from_object' => $fromObject,
'to_object' => $toObject,
'reason' => $e->getMessage(),
]);
}
}
return $associationData;
}
/**
* @throws \Exception
*/
private function getNoteAssociationType(NoteObject $noteObject): string
{
return match($noteObject) {
NoteObject::Opportunity => 'note_to_deal',
NoteObject::Lead, NoteObject::Contact => 'note_to_contact', // or 'note_to_lead' if your portal supports it
NoteObject::Account => 'note_to_company',
NoteObject::Call, NoteObject::Event => throw new \Exception('Not supported'),
};
}
/**
* @throws \Exception
*/
private function getNoteObject(NoteObject $noteObject): string
{
return match($noteObject) {
NoteObject::Opportunity => 'deal',
NoteObject::Lead, NoteObject::Contact => 'contact',
NoteObject::Account => 'company',
NoteObject::Call, NoteObject::Event => throw new \Exception('Not supported'),
};
}
public function addAssociations(string $objectType, string $associationType, array $payload): Response
{
$endpoint = "/crm/v4/associations/$objectType/$associationType/batch/create";
return $this->makeRequest($endpoint, 'POST', $payload);
}
public function removeAssociations(string $objectType, string $associationType, array $payload): Response
{
$endpoint = "/crm/v4/associations/$objectType/$associationType/batch/archive";
return $this->makeRequest($endpoint, 'POST', $payload);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
45
1
41
66
Previous Highlighted Error
Next Highlighted Error
SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993
SELECT * FROM users WHERE id = 25061;
SELECT * FROM crm_profiles WHERE crm_configuration_id = 994;
SELECT * FROM crm_profiles WHERE user_id = 25061;
select * from crm_configurations where id = 834;
SELECT * FROM teams WHERE id = 882;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;
SELECT * FROM contacts where crm_configuration_id = 834;
SELECT * FROM opportunities WHERE team_id = 933
# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');
AND id IN (8482561,18352941,19042734,19232139,19445140,19472541);
SELECT * FROM opportunity_contacts
WHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 485; #
SELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
select crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id
where crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')
# and l.converted_at IS NOT NULL
;
# [PASSWORD_DOTS]
SELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')
and opportunity_id IS NULL
order by id desc;
SELECT * FROM teams WHERE id = 604; # 598
SELECT * FROM activities WHERE id = 74410828; # [EMAIL]
SELECT * FROM accounts WHERE id = 20068382;
SELECT * FROM accounts WHERE id = 35186038;
SELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 559 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;
select * from sidekick_settings where team_id = 781;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100
SELECT * FROM crm_layouts WHERE crm_configuration_id = 711;
SELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL
and is_internal = 0 and status = 'completed'
order by id desc;
SELECT * FROM crm_layout_entities
WHERE crm_layout_id IN (2352, 2353);
;
SELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 556 and sa.provider = 'hubspot';
SELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;
SELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;
select * from contacts
where crm_configuration_id = 530
and crm_provider_id = 872252;
select * from activities where crm_configuration_id = 530
and user_id = 14343 and type like '%softphone%'
and created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya
SELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);
SELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t
JOIN crm_configurations c ON t.id = c.team_id
WHERE t.status = 'active';
SELECT * FROM teams where id = 1091;
SELECT * FROM crm_configurations where team_id = 1091;
SELECT * FROM activity_providers where team_id = 1091;
SELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT * FROM teams WHERE name LIKE '%Leadventure%';
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1091 and sa.provider = 'salesforce';
SELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812
SELECT * FROM teams where id = 862;
SELECT * FROM crm_configurations where team_id = 862;
SELECT * FROM activity_providers where team_id = 862;
SELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')
and provider NOT IN ('hubspot', 'aircall')
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by id desc;
SELECT t.id, crm.id, crm.provider, ap.* FROM teams t
join crm_configurations crm on t.id = crm.team_id
join activity_providers ap on t.id = ap.team_id
where t.status = 'active' and ap.is_enabled = 1
and crm.provider = 'hubspot'
and ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',
'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');
SELECT * FROM teams where id = 1068;
SELECT * FROM crm_configurations where team_id = 1068;
SELECT * FROM activity_providers where team_id = 1068;
SELECT * FROM activities a
where crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')
and a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'
)
# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'
order by a.id desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1068 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 933 and sa.provider = 'hubspot';
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262
SELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 882 and sa.provider = 'hubspot';
select * from crm_layouts where crm_configuration_id = 834;
select * from crm_layout_entities where crm_layout_id = 2780;
select * from crm_fields where id IN (321153,321192,321193,321194);
SELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1057 and sa.provider = 'hubspot';
SELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8
SELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20
SELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last
SELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10
SELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;
SELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th
# [PASSWORD_DOTS]
SELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #
SELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;
SELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;
select * from users where team_id = 51; # 7783
SELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130
select * from activity_searches where user_id = 7783;
select * from activity_search_filters where activity_search_id IN (32291, 32292);
SELECT asf.activity_search_id, asf.id, asf.value
FROM activity_search_filters asf
WHERE asf.filter = 'group_id'
AND asf.value IN (
SELECT CONCAT(
HEX(SUBSTR(uuid, 5, 4)), '-',
HEX(SUBSTR(uuid, 3, 2)), '-',
HEX(SUBSTR(uuid, 1, 2)), '-',
HEX(SUBSTR(uuid, 9, 2)), '-',
HEX(SUBSTR(uuid, 11))
)
FROM groups
WHERE deleted_at ...
|
85250
|
NULL
|
NULL
|
NULL
|
|
85250
|
2920
|
4
|
2026-05-28T12:14:55.793467+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970495793_m1.jpg...
|
PhpStorm
|
faVsco.js – Client.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
PhpStormFileEditViewNavigateCodeRefactorRunToolsGi PhpStormFileEditViewNavigateCodeRefactorRunToolsGitWindowHelpec2-user@ip-10-30-129-190:~screenpipe"O ₴4‹$0(ah]100% <78• Thu 28 May 15:14:55181ec2-user@ip-10-30-140-….₴7DOCKER#_####_#####\\###||\#/V~'881DEV (-zsh)O [EMAIL] Linux 2023 (ECS Optimized)_/m/For documentation, visit [URL_WITH_CREDENTIALS] ~]$ exitlogoutConnection to jiminny-prod-ecsi closed.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ applukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ vprodWarning: Permanently added 'jiminny-prod-ecs1' (ED25519) to the list of known hosts.A newer release of "Amazon Linux" is available.Version 2023.10.20260330:Version 2023.11.20260406:Version 2023.11.20260413:Version2023.11.20260427:Version2023.11.20260505:Version 2023.11.20260509:Version 2023.11.20260511:Version 2023.11.20260514:Run "/usr/bin/dnf check-release-update" for full release and version update info#_~\ ####_\ #####\\###1\#/Amazon Linux 2023 (ECS Optimized)/m/'For documentation, visit [URL_WITH_CREDENTIALS] ~]$ client_loop: send disconnect: Broken pipeukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-relay) $I...
|
NULL
|
-6914738773934183330
|
NULL
|
idle
|
ocr
|
NULL
|
PhpStormFileEditViewNavigateCodeRefactorRunToolsGi PhpStormFileEditViewNavigateCodeRefactorRunToolsGitWindowHelpec2-user@ip-10-30-129-190:~screenpipe"O ₴4‹$0(ah]100% <78• Thu 28 May 15:14:55181ec2-user@ip-10-30-140-….₴7DOCKER#_####_#####\\###||\#/V~'881DEV (-zsh)O [EMAIL] Linux 2023 (ECS Optimized)_/m/For documentation, visit [URL_WITH_CREDENTIALS] ~]$ exitlogoutConnection to jiminny-prod-ecsi closed.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ applukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ vprodWarning: Permanently added 'jiminny-prod-ecs1' (ED25519) to the list of known hosts.A newer release of "Amazon Linux" is available.Version 2023.10.20260330:Version 2023.11.20260406:Version 2023.11.20260413:Version2023.11.20260427:Version2023.11.20260505:Version 2023.11.20260509:Version 2023.11.20260511:Version 2023.11.20260514:Run "/usr/bin/dnf check-release-update" for full release and version update info#_~\ ####_\ #####\\###1\#/Amazon Linux 2023 (ECS Optimized)/m/'For documentation, visit [URL_WITH_CREDENTIALS] ~]$ client_loop: send disconnect: Broken pipeukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-relay) $I...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85249
|
2921
|
4
|
2026-05-28T12:14:26.861977+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970466861_m2.jpg...
|
PhpStorm
|
faVsco.js – Client.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
#12121 on JY-20963-fix-im Project: faVsco.js, menu
#12121 on JY-20963-fix-import-on-deleted-entity, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
1
2
69
3
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Hubspot;
use HubSpot\Client\Crm\Deals\ApiException as DealApiException;
use HubSpot\Client\Crm\Contacts\ApiException as ContactApiException;
use HubSpot\Client\Crm\Companies\ApiException as CompanyApiException;
use HubSpot\Client\Crm\Contacts\Model\SimplePublicObjectWithAssociations as ContactsWithAssociations;
use HubSpot\Client\Crm\Companies\Model\SimplePublicObjectWithAssociations as CompaniesWithAssociations;
use HubSpot\Client\Crm\Deals\Model\SimplePublicObjectWithAssociations as DealWithAssociations;
use HubSpot\Client\Crm\Objects\Model\SimplePublicObjectInput;
use HubSpot\Client\Crm\Objects\Model\SimplePublicObjectWithAssociations as ObjectWithAssociations;
use HubSpot\Client\Crm\Pipelines\Model\Error;
use HubSpot\Client\Crm\Pipelines\Model\PipelineStage;
use HubSpot\Client\Crm\Properties\Model\Property;
use HubSpot\Discovery\Discovery;
use Jiminny\Exceptions\CrmException;
use Jiminny\Exceptions\RateLimitException;
use Jiminny\Exceptions\SocialAccountTokenInvalidException;
use Jiminny\Jobs\Crm\NoteObject;
use Jiminny\Models\Crm\Field;
use Jiminny\Services\Crm\BaseClient;
use Jiminny\Services\Crm\Hubspot\DTO\Response\Owner;
use Jiminny\Services\SocialAccountService;
use SevenShores\Hubspot\Exceptions\BadRequest;
use SevenShores\Hubspot\Exceptions\HubspotException;
use SevenShores\Hubspot\Factory;
use SevenShores\Hubspot\Http\Response;
use Jiminny\Services\Crm\Hubspot\Pagination\HubspotPaginationService;
use Illuminate\Support\Facades\Redis;
use Throwable;
/**
* @phpstan-type CrmFieldOption array{id:string, label:string, value?:string}
*/
class Client extends BaseClient implements HubspotClientInterface
{
public const string MIN_API_VERSION = '2';
public const string BASE_URL = '[URL_WITH_CREDENTIALS] T
*
* @param callable(): T $apiCall The API call to execute
*
* @throws RateLimitException When rate limit is hit or cached rate limit is active
*
* @return T The result of the API call
*/
private function executeRequest(callable $apiCall)
{
$cacheKey = $this->getRateLimitCacheKey();
$cachedExpiresAt = Redis::get($cacheKey);
if (is_string($cachedExpiresAt) && is_numeric($cachedExpiresAt)) {
$remaining = max(1, (int) $cachedExpiresAt - time());
throw new RateLimitException(
'Hubspot rate limit (cached circuit-breaker)',
$remaining,
);
}
try {
return $apiCall();
} catch (Throwable $e) {
if ($this->isHubspotRateLimit($e)) {
$retryAfter = $this->parseRetryAfter($e);
// NX: only the first job to receive a 429 in this burst sets the key.
// Subsequent 429s in the same burst leave the TTL untouched so the
// window is not reset by every concurrent job hitting the limit.
Redis::set($cacheKey, (string) (time() + $retryAfter), 'EX', $retryAfter, 'NX');
$this->log->warning('[Hubspot] Received 429 from API', [
'team_id' => $this->config->team_id,
'config_id' => $this->config->getId(),
'retry_after' => $retryAfter,
'reason' => $e->getMessage(),
]);
throw new RateLimitException('Hubspot returned 429', $retryAfter, $e);
}
throw $e;
}
}
private function getRateLimitCacheKey(): string
{
return sprintf('hubspot:ratelimit:config:%d', $this->config->getId());
}
private function isHubspotRateLimit(Throwable $e): bool
{
if ($e instanceof BadRequest
|| $e instanceof DealApiException
|| $e instanceof ContactApiException
|| $e instanceof CompanyApiException
|| $e instanceof \GuzzleHttp\Exception\RequestException
) {
return (int) $e->getCode() === 429;
}
return false;
}
private function parseRetryAfter(Throwable $e): int
{
if (method_exists($e, 'getResponseHeaders')) {
$headers = $e->getResponseHeaders() ?: [];
$value = $headers['Retry-After'] ?? $headers['retry-after'] ?? null;
if (is_array($value)) {
$value = $value[0] ?? null;
}
if (is_numeric($value)) {
return (int) $value;
}
}
$message = strtolower($e->getMessage());
if (str_contains($message, 'daily')) {
return 600;
}
if (str_contains($message, 'ten secondly')) {
return 10;
}
if (str_contains($message, 'secondly')) {
return 1;
}
$this->log->warning('[Hubspot] No retry-after header or known message, using default', [
'exception_class' => get_class($e),
'message' => $message,
]);
return 10;
}
public function getMinimumApiVersion(): string
{
return self::MIN_API_VERSION;
}
public function getInstance(): Factory
{
return new Factory([
'key' => $this->accessToken,
'oauth2' => true,
'base_url' => $this->baseUrl,
]);
}
public function getNewInstance(): Discovery
{
return \HubSpot\Factory::createWithAccessToken($this->accessToken);
}
/**
* Secondly and daily limits for Hubspot API
*
* Product Tier: Free & Starter | Professional & Enterprise | API add-on (any tier)
* Burst: 100/10 seconds | 150/10 seconds | 200/10 seconds
* Daily: 250,000 | 500,000 | 1,000,000
*
* Official documentation states: The search endpoints are rate limited to five requests per second.
* Since with 5 RPS were still hitting secondly rate limits we lowered it to 4
*/
public function getPaginatedData(array $payload, string $type, int $offset = 0): array
{
$total = 0;
$lastId = null;
$rows = [];
foreach ($this->getPaginatedDataGenerator($payload, $type, $offset, $total, $lastId) as $row) {
$rows[] = $row;
}
return ['results' => $rows, 'total' => $total, 'last_record' => $lastId];
}
/**
* @throws HubspotException
* @throws SocialAccountTokenInvalidException
* @throws BadRequest
*/
public function getPaginatedDataGenerator(
array $payload,
string $type,
int $offset = 0,
int &$total = 0,
?string &$lastRecordId = null
): \Generator {
return $this->paginationService->getPaginatedDataGenerator(
$this,
$payload,
$type,
$offset,
$total,
$lastRecordId
);
}
/**
* Execute a search request against HubSpot CRM objects with rate limiting.
*
* @param string $objectType The object type ('deals', 'companies', 'contacts', 'calls')
* @param array<string, mixed> $payload The search payload with filters, sorts, properties, etc.
*
* @throws RateLimitException When rate limit is hit
* @throws HubspotException On API errors
*
* @return array The search response with 'results', 'total', 'paging' keys
*/
public function search(string $objectType, array $payload): array
{
$endpoint = self::BASE_URL . "/crm/v3/objects/{$objectType}/search";
return $this->executeRequest(function () use ($endpoint, $payload) {
$response = $this->getInstance()->getClient()->request('POST', $endpoint, ['json' => $payload]);
return $response->toArray();
});
}
/**
* @throws DealApiException
* @throws CrmException
*/
public function getOpportunityById(string $crmId, array $fields): array
{
try {
$deal = $this->getNewInstance()->crm()->deals()->basicApi()->getById(
$crmId,
implode(',', $fields),
'companies,contacts'
);
} catch (DealApiException $e) {
$this->log->info('[Hubspot] Failed to fetch opportunity', [
'crm_id' => $crmId,
'reason' => $e->getMessage(),
]);
throw $e;
}
if (! $deal instanceof DealWithAssociations) {
throw new CrmException('Deal not found');
}
return [
'id' => $deal->getId(),
'properties' => $deal->getProperties(),
'associations' => $deal->getAssociations(),
];
}
/**
* Generic batch read method for HubSpot objects
*
* @param string $objectType The object type ('deals', 'companies', 'contacts')
* @param array<string> $crmIds Array of HubSpot object IDs (max 100)
* @param array<string> $fields Array of property names to fetch
*
* @return array<string, array> Array keyed by CRM ID with object data
*/
private function batchReadObjects(string $objectType, array $crmIds, array $fields): array
{
if (empty($crmIds)) {
return [];
}
$this->validateBatchSize($objectType, $crmIds);
$this->ensureValidToken();
try {
$batchConfig = $this->createBatchConfiguration($objectType);
$batchReadRequest = $this->prepareBatchRequest($batchConfig, $crmIds, $fields);
$response = $batchConfig['api']->read($batchReadRequest);
$this->validateApiResponse($response, $objectType);
$results = $this->processApiResults($response);
$this->logBatchResults($objectType, $crmIds, $results);
return $results;
} catch (\Throwable $e) {
$this->handleBatchError($e, $objectType, $crmIds);
}
}
private function validateBatchSize(string $objectType, array $crmIds): void
{
if (count($crmIds) > 100) {
throw new \InvalidArgumentException("Batch size cannot exceed 100 {$objectType}");
}
}
private function createBatchConfiguration(string $objectType): array
{
$configurations = [
'deals' => [
'batchReadRequest' => new \HubSpot\Client\Crm\Deals\Model\BatchReadInputSimplePublicObjectId(),
'inputClass' => \HubSpot\Client\Crm\Deals\Model\SimplePublicObjectId::class,
'api' => $this->getNewInstance()->crm()->deals()->batchApi(),
],
'companies' => [
'batchReadRequest' => new \HubSpot\Client\Crm\Companies\Model\BatchReadInputSimplePublicObjectId(),
'inputClass' => \HubSpot\Client\Crm\Companies\Model\SimplePublicObjectId::class,
'api' => $this->getNewInstance()->crm()->companies()->batchApi(),
],
'contacts' => [
'batchReadRequest' => new \HubSpot\Client\Crm\Contacts\Model\BatchReadInputSimplePublicObjectId(),
'inputClass' => \HubSpot\Client\Crm\Contacts\Model\SimplePublicObjectId::class,
'api' => $this->getNewInstance()->crm()->contacts()->batchApi(),
],
];
if (! isset($configurations[$objectType])) {
throw new \InvalidArgumentException("Unsupported object type: {$objectType}");
}
return $configurations[$objectType];
}
private function prepareBatchRequest(array $batchConfig, array $crmIds, array $fields): object
{
$batchReadRequest = $batchConfig['batchReadRequest'];
$inputClass = $batchConfig['inputClass'];
$inputs = array_map(function ($crmId) use ($inputClass) {
$input = new $inputClass();
$input->setId($crmId);
return $input;
}, $crmIds);
$batchReadRequest->setInputs($inputs);
$batchReadRequest->setProperties($fields);
return $batchReadRequest;
}
private function validateApiResponse($response, string $objectType): void
{
if (! $response) {
throw new CrmException("HubSpot API returned null response for {$objectType} batch read");
}
}
private function processApiResults($response): array
{
$results = [];
$responseResults = $response->getResults();
if ($responseResults) {
foreach ($responseResults as $object) {
if ($object && $object->getId()) {
$results[$object->getId()] = [
'id' => $object->getId(),
'properties' => $object->getProperties() ?: [],
];
}
}
}
return $results;
}
private function logBatchResults(string $objectType, array $crmIds, array $results): void
{
$this->log->info("[HubSpot] Batch fetched {$objectType}", [
'requested_count' => count($crmIds),
'returned_count' => count($results),
'crm_ids' => $crmIds,
]);
}
private function handleBatchError(\Throwable $e, string $objectType, array $crmIds): void
{
$errorMessage = $e->getMessage() ?: 'Unknown error';
$errorTrace = $e->getTraceAsString() ?: 'No trace available';
$this->log->error("[HubSpot] Failed to batch fetch {$objectType}", [
'crm_ids' => $crmIds,
'error' => $errorMessage,
'trace' => $errorTrace,
]);
throw new CrmException("Failed to batch fetch {$objectType}: " . $errorMessage);
}
/**
* Batch read multiple opportunities by their CRM IDs
*
* @param array<string> $crmIds Array of HubSpot deal IDs (max 100)
* @param array<string> $fields Array of property names to fetch
*
* @return array<string, array> Array keyed by CRM ID with opportunity data
*/
public function getOpportunitiesByIds(array $crmIds, array $fields): array
{
return $this->batchReadObjects('deals', $crmIds, $fields);
}
/**
* Batch read multiple companies by their CRM IDs
*
* @param array<string> $crmIds Array of HubSpot company IDs (max 100)
* @param array<string> $fields Array of property names to fetch
*
* @return array<string, array> Array keyed by CRM ID with company data
*/
public function getCompaniesByIds(array $crmIds, array $fields): array
{
return $this->batchReadObjects('companies', $crmIds, $fields);
}
/**
* Batch read multiple contacts by their CRM IDs
*
* @param array<string> $crmIds Array of HubSpot contact IDs (max 100)
* @param array<string> $fields Array of property names to fetch
*
* @return array<string, array> Array keyed by CRM ID with contact data
*/
public function getContactsByIds(array $crmIds, array $fields): array
{
return $this->batchReadObjects('contacts', $crmIds, $fields);
}
/**
* @throws CompanyApiException
* @throws CrmException
*/
public function getAccountById(string $crmId, array $fields): array
{
try {
$company = $this->getNewInstance()->crm()->companies()->basicApi()->getById(
$crmId,
implode(',', $fields),
);
} catch (CompanyApiException $e) {
$this->log->info('[Hubspot] Failed to fetch account', [
'crm_id' => $crmId,
'reason' => $e->getMessage(),
]);
throw $e;
}
if (! $company instanceof CompaniesWithAssociations) {
throw new CrmException('Account not found');
}
return [
'id' => $company->getId(),
'properties' => $company->getProperties(),
];
}
/**
* @throws ContactApiException
* @throws CrmException
*/
public function getContactById(string $crmId, array $fields): array
{
try {
$contact = $this->getNewInstance()->crm()->contacts()->basicApi()->getById(
$crmId,
implode(',', $fields)
);
} catch (ContactApiException $e) {
$this->log->info('[Hubspot] Failed to fetch contact', [
'crm_id' => $crmId,
'reason' => $e->getMessage(),
]);
throw $e;
}
if (! $contact instanceof ContactsWithAssociations) {
throw new CrmException('Contact not found');
}
return [
'id' => $contact->getId(),
'properties' => $contact->getProperties(),
];
}
/**
* This is email search request that Hubspot offers as GET (more generous quota)
*/
public function getContactByEmail(string $email, array $fields = []): array
{
try {
$contact = $this->getNewInstance()->crm()->contacts()->basicApi()->getById(
$email,
implode(',', $fields),
null,
false,
'email'
);
return [
'id' => $contact->getId(),
'properties' => $contact->getProperties(),
];
} catch (ContactApiException $e) {
$this->log->info('[Hubspot] Failed to fetch contact', [
'email' => $email,
'reason' => $e->getMessage(),
]);
return [];
}
}
/**
* @throws CrmException
*/
public function fetchProperty(string $objectType, string $propertyId): Property
{
$result = $this->getNewInstance()->crm()->properties()->coreApi()->getByName($objectType, $propertyId);
if (! $result instanceof Property) {
$this->log->error('[Hubspot] Failed to fetch property', [
'object_type' => $objectType,
'property_id' => $propertyId,
'reason' => $result->getMessage(),
]);
throw new CrmException('Failed to fetch property');
}
return $result;
}
/**
* @return array<CrmFieldOption>
*/
public function fetchPropertyOptions(string $objectType, string $propertyId): array
{
/** @var array<CrmFieldOption> */
return $this->fetchProperty($objectType, $propertyId)->getOptions();
}
/**
* @return array<array{id:string, label:string, deleted:bool}>
*/
public function fetchCallDispositions(): array
{
/** @var Response $response */
$response = $this->getInstance()->engagements()->getCallDispositions();
/**
* @var array<array{
* id:string,
* label:string,
* deleted: bool
* }>
*/
return $response->toArray();
}
/**
* @return array<CrmFieldOption>
*/
public function fetchOpportunityPipelineStages(): array
{
$stages = [];
$apiResponse = $this->getNewInstance()->crm()->pipelines()->pipelinesApi()->getAll('deals');
if ($apiResponse instanceof Error) {
$this->log->error('[Hubspot] Failed to fetch opportunity pipelines', [
'reason' => $apiResponse->getMessage(),
]);
return [];
}
foreach ($apiResponse->getResults() as $pipeline) {
$pipelineStages = array_map(
static function (PipelineStage $stage) {
return [
'id' => $stage->getId(),
'label' => $stage->getLabel(),
];
},
$pipeline->getStages()
);
$stages = array_merge($stages, $pipelineStages);
}
return $stages;
}
public function fetchOpportunityPipelines(): array
{
$pipelines = [];
try {
$apiResponse = $this->makeRequest('/crm/v3/pipelines/deals');
} catch (\Exception $e) {
$this->log->info('[Hubspot] Failed to fetch opportunity pipelines', [
'reason' => $e->getMessage(),
]);
return [];
}
$response = $apiResponse->toArray();
foreach ($response['results'] as $pipeline) {
$pipelines[] = [
'id' => $pipeline['id'],
'label' => $pipeline['label'],
];
}
return $pipelines;
}
/**
* @return array<CrmFieldOption>
*/
public function fetchMeetingOutcomeFieldOptions(Field $field): array
{
return $field->getCrmProviderId() === 'meetingOutcome'
? $this->fetchMeetingOutcomeTypes()
: $this->fetchCallActivityTypes();
}
public function fetchMeetingOutcomeTypes(): array
{
return $this->extractMeetingTypeOptions(
'[URL_WITH_CREDENTIALS] Response $response */
$response = $this->getInstance()
->getClient()
->request('GET', $endpoint);
/**
* @var array<array{
* value: string,
* label: string,
* displayOrder: int
* }> $optionData
*/
$optionData = $response->toArray()['options'] ?? [];
$options = [];
foreach ($optionData as $item) {
$options[] = [
'id' => $item['value'],
'value' => $item['value'],
'label' => $item['label'],
'display_order' => $item['displayOrder'],
];
}
return $options;
}
/**
* @return array<CrmFieldOption>
*/
public function fetchDispositionFieldOptions(): array
{
$options = [];
$dispositions = $this->fetchCallDispositions();
foreach ($dispositions as $disposition) {
if ($disposition['deleted'] !== false) {
continue;
}
$option['value'] = $disposition['id'];
$option['id'] = $disposition['id'];
$option['label'] = $disposition['label'];
$options[] = $option;
}
return $options;
}
/**
* @return array<CrmFieldOption>
*/
public function fetchOpportunityFieldOptions(Field $field): array
{
if ($field->isStageField()) {
return $this->fetchOpportunityPipelineStages();
}
if ($field->isPipelineField()) {
return $this->fetchOpportunityPipelines();
}
return $this->fetchPropertyOptions('deals', $field->getCrmProviderId());
}
/**
* @throws BadRequest
* @throws HubspotException
*/
public function makeRequest(string $endpoint, $method = 'GET', $payload = [], ?string $queryString = null)
{
$endpoint = self::BASE_URL . $endpoint;
if ($method === 'GET') {
return $this->getInstance()->getClient()?->request(
method: $method,
endpoint: $endpoint,
query_string: $queryString
);
} else {
return $this->getInstance()->getClient()->request($method, $endpoint, [
'json' => ($payload),
]);
}
}
/**
* @throws BadRequest
* @throws HubspotException
*/
public function createMeeting(array $payload): Response
{
$endpoint = '/crm/v3/objects/meetings';
return $this->makeRequest($endpoint, 'POST', $payload);
}
/**
* @throws BadRequest
* @throws HubspotException
*/
public function updateMeeting(string $meetingId, array $payload): Response
{
$endpoint = '/crm/v3/objects/meetings/' . $meetingId;
return $this->makeRequest($endpoint, 'PATCH', $payload);
}
/**
* @throws \Exception
*/
public function createNote(
string $body,
string $ownerId,
int $timestamp,
string $objectId,
NoteObject $noteObject
): ?string {
try {
$noteInput = new SimplePublicObjectInput([
'properties' => [
'hs_note_body' => $body,
'hubspot_owner_id' => $ownerId,
'hs_timestamp' => $timestamp,
],
]);
// Create note
$note = $this->getNewInstance()->crm()->objects()->basicApi()->create('note', $noteInput);
$this->getNewInstance()->crm()->objects()->associationsApi()->create(
'note',
$note->getId(),
$this->getNoteObject($noteObject),
$objectId,
$this->getNoteAssociationType($noteObject),
);
return $note->getId();
} catch (\Exception $e) {
$this->log->error('[Hubspot] Failed to create note', [
'objectId' => $objectId,
'noteObject' => $noteObject->getObjectType(),
'reason' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return null;
}
public function updateEngagement(string $objectId, array $engagement, array $metadata): void
{
$this->getInstance()->engagements()->update($objectId, $engagement, $metadata);
}
public function getEngagementData(string $engagementId): array
{
$engagement = $this->getInstance()->engagements()->get($engagementId);
return $engagement->toArray();
}
public function createEngagement(array $engagement, array $associations, array $metadata): Response
{
return $this->getInstance()
->engagements()
->create($engagement, $associations, $metadata);
}
public function isUnauthorizedException(\Exception $e): bool
{
// Check for specific HubSpot API exception types first
if ($e instanceof BadRequest) {
// BadRequest can contain 401 status codes
return $e->getCode() === 401;
}
// Check for HTTP client exceptions with status codes
if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
$response = $e->getResponse();
if ($response !== null) {
return $response->getStatusCode() === 401;
}
}
// Check for Guzzle HTTP exceptions
if ($e instanceof \GuzzleHttp\Exception\ClientException) {
return $e->getCode() === 401;
}
// Fallback to string matching as last resort, but be more specific
$message = strtolower($e->getMessage());
return str_contains($message, '401 unauthorized') ||
str_contains($message, 'http 401') ||
str_contains($message, 'status code 401') ||
(preg_match('/\b401\b/', $message) && str_contains($message, 'unauthorized'));
}
/**
* Validates and refreshes the access token if needed before API requests.
* This ensures long-running processes don't fail due to token expiration.
*
* @throws SocialAccountTokenInvalidException
*/
public function ensureValidToken(): void
{
if ($this->oauthAccount === null) {
return;
}
$newToken = $this->tokenManager->ensureValidToken($this->oauthAccount);
if ($newToken !== null) {
$this->accessToken = $newToken;
}
}
public function getConfig()
{
return $this->config;
}
// returns only active (archived=false)
public function getOwners(): array
{
return $this->getNewInstance()->crm()->owners()->getAll();
}
/**
* @param bool $archived
*
* @return array<Owner>|[]
*/
public function getOwnersArchived(bool $archived = true): array
{
$endpoint = '/crm/v3/owners';
$queryParams = [
'archived' => $archived ? 'true' : 'false',
];
$queryString = http_build_query($queryParams);
$owners = [];
try {
$response = $this->makeRequest(endpoint: $endpoint, queryString: $queryString);
$responseData = $response?->toArray();
foreach ($responseData['results'] as $result) {
try {
$owners[] = Owner::create($result);
} catch (Throwable $e) {
$this->log->error('[HubSpot] Failed to process owner data', [
'result' => $result,
'error' => $e->getMessage(),
]);
continue;
}
}
} catch (Throwable $e) {
$this->log->error('HubSpot] Failed to fetch owners', [
'archived' => $archived,
'error' => $e->getMessage(),
]);
return [];
}
return $owners;
}
public function getMeeting(string $engagementId): ObjectWithAssociations
{
return $this->getNewInstance()->crm()->objects()->basicApi()
->getById('meeting', $engagementId, null, 'contact,company,deal');
}
public function deleteEngagement(string $engagementId): void
{
$this->getInstance()->engagements()->delete((int) $engagementId);
}
public function getAssociationsData(array $ids, string $fromObject, string $toObject): array
{
$associationData = [];
$idChunks = array_chunk($ids, self::ASSOCIATIONS_BATCH_SIZE_LIMIT);
foreach ($idChunks as $idChunk) {
try {
$batchInput = new \HubSpot\Client\Crm\Associations\Model\BatchInputPublicObjectId();
$batchInput->setInputs(array_map(function ($id) {
$publicObjectId = new \HubSpot\Client\Crm\Associations\Model\PublicObjectId();
$publicObjectId->setId($id);
return $publicObjectId;
}, $idChunk));
$associatedObjectsData = $this
->getNewInstance()
->crm()
->associations()
->batchApi()
->read($fromObject, $toObject, $batchInput);
if ($associatedObjectsData instanceof \HubSpot\Client\Crm\Associations\Model\BatchResponsePublicAssociationMulti) {
foreach ($associatedObjectsData->getResults() as $association) {
$from = $association->getFrom()->getId();
$toAssociations = $association->getTo();
if (! empty($toAssociations)) {
$associationData[$from] = array_map(function ($item) {
return $item->getId();
}, $toAssociations);
}
}
}
} catch (\Exception $e) {
$this->log->error('[Hubspot] Failed to fetch associations', [
'from_object' => $fromObject,
'to_object' => $toObject,
'reason' => $e->getMessage(),
]);
}
}
return $associationData;
}
/**
* @throws \Exception
*/
private function getNoteAssociationType(NoteObject $noteObject): string
{
return match($noteObject) {
NoteObject::Opportunity => 'note_to_deal',
NoteObject::Lead, NoteObject::Contact => 'note_to_contact', // or 'note_to_lead' if your portal supports it
NoteObject::Account => 'note_to_company',
NoteObject::Call, NoteObject::Event => throw new \Exception('Not supported'),
};
}
/**
* @throws \Exception
*/
private function getNoteObject(NoteObject $noteObject): string
{
return match($noteObject) {
NoteObject::Opportunity => 'deal',
NoteObject::Lead, NoteObject::Contact => 'contact',
NoteObject::Account => 'company',
NoteObject::Call, NoteObject::Event => throw new \Exception('Not supported'),
};
}
public function addAssociations(string $objectType, string $associationType, array $payload): Response
{
$endpoint = "/crm/v4/associations/$objectType/$associationType/batch/create";
return $this->makeRequest($endpoint, 'POST', $payload);
}
public function removeAssociations(string $objectType, string $associationType, array $payload): Response
{
$endpoint = "/crm/v4/associations/$objectType/$associationType/batch/archive";
return $this->makeRequest($endpoint, 'POST', $payload);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12121 on JY-20963-fix-import-on-deleted-entity, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.11569149,"height":0.025538707},"on_screen":true,"help_text":"Pull request #12121 exists for current branch JY-20963-fix-import-on-deleted-entity","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8374335,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"bounds":{"left":0.85272604,"top":0.019952115,"width":0.062832445,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.3587101,"top":0.15003991,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"2","depth":4,"bounds":{"left":0.36801863,"top":0.15003991,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"69","depth":4,"bounds":{"left":0.37799203,"top":0.15003991,"width":0.010305851,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"3","depth":4,"bounds":{"left":0.39029256,"top":0.15003991,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.39993352,"top":0.14844373,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.40724733,"top":0.14844373,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Hubspot;\n\nuse HubSpot\\Client\\Crm\\Deals\\ApiException as DealApiException;\nuse HubSpot\\Client\\Crm\\Contacts\\ApiException as ContactApiException;\nuse HubSpot\\Client\\Crm\\Companies\\ApiException as CompanyApiException;\nuse HubSpot\\Client\\Crm\\Contacts\\Model\\SimplePublicObjectWithAssociations as ContactsWithAssociations;\nuse HubSpot\\Client\\Crm\\Companies\\Model\\SimplePublicObjectWithAssociations as CompaniesWithAssociations;\nuse HubSpot\\Client\\Crm\\Deals\\Model\\SimplePublicObjectWithAssociations as DealWithAssociations;\nuse HubSpot\\Client\\Crm\\Objects\\Model\\SimplePublicObjectInput;\nuse HubSpot\\Client\\Crm\\Objects\\Model\\SimplePublicObjectWithAssociations as ObjectWithAssociations;\nuse HubSpot\\Client\\Crm\\Pipelines\\Model\\Error;\nuse HubSpot\\Client\\Crm\\Pipelines\\Model\\PipelineStage;\nuse HubSpot\\Client\\Crm\\Properties\\Model\\Property;\nuse HubSpot\\Discovery\\Discovery;\nuse Jiminny\\Exceptions\\CrmException;\nuse Jiminny\\Exceptions\\RateLimitException;\nuse Jiminny\\Exceptions\\SocialAccountTokenInvalidException;\nuse Jiminny\\Jobs\\Crm\\NoteObject;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Services\\Crm\\BaseClient;\nuse Jiminny\\Services\\Crm\\Hubspot\\DTO\\Response\\Owner;\nuse Jiminny\\Services\\SocialAccountService;\nuse SevenShores\\Hubspot\\Exceptions\\BadRequest;\nuse SevenShores\\Hubspot\\Exceptions\\HubspotException;\nuse SevenShores\\Hubspot\\Factory;\nuse SevenShores\\Hubspot\\Http\\Response;\nuse Jiminny\\Services\\Crm\\Hubspot\\Pagination\\HubspotPaginationService;\nuse Illuminate\\Support\\Facades\\Redis;\nuse Throwable;\n\n/**\n * @phpstan-type CrmFieldOption array{id:string, label:string, value?:string}\n */\nclass Client extends BaseClient implements HubspotClientInterface\n{\n public const string MIN_API_VERSION = '2';\n\n public const string BASE_URL = 'https://api.hubapi.com';\n\n public const int ASSOCIATIONS_BATCH_SIZE_LIMIT = 1000;\n\n private HubspotPaginationService $paginationService;\n private HubspotTokenManager $tokenManager;\n\n public function __construct(\n SocialAccountService $socialAccountService,\n HubspotPaginationService $paginationService,\n HubspotTokenManager $tokenManager\n ) {\n parent::__construct($socialAccountService);\n $this->paginationService = $paginationService;\n $this->tokenManager = $tokenManager;\n\n $this->setBaseUrl(self::BASE_URL);\n $this->setVersion(self::MIN_API_VERSION);\n }\n\n /**\n * Execute a HubSpot API call with rate limit handling.\n *\n * On a 429, stores the absolute expiry timestamp with SET NX (first writer wins).\n * This means all subsequent jobs that also receive 429 in the same burst do not\n * reset the TTL — the window is anchored to the first 429, not the last.\n * Readers compute the remaining wait from the stored timestamp, so jobs that check\n * the cache near expiry are not delayed longer than necessary.\n *\n * @template T\n *\n * @param callable(): T $apiCall The API call to execute\n *\n * @throws RateLimitException When rate limit is hit or cached rate limit is active\n *\n * @return T The result of the API call\n */\n private function executeRequest(callable $apiCall)\n {\n $cacheKey = $this->getRateLimitCacheKey();\n\n $cachedExpiresAt = Redis::get($cacheKey);\n if (is_string($cachedExpiresAt) && is_numeric($cachedExpiresAt)) {\n $remaining = max(1, (int) $cachedExpiresAt - time());\n\n throw new RateLimitException(\n 'Hubspot rate limit (cached circuit-breaker)',\n $remaining,\n );\n }\n\n try {\n return $apiCall();\n } catch (Throwable $e) {\n if ($this->isHubspotRateLimit($e)) {\n $retryAfter = $this->parseRetryAfter($e);\n\n // NX: only the first job to receive a 429 in this burst sets the key.\n // Subsequent 429s in the same burst leave the TTL untouched so the\n // window is not reset by every concurrent job hitting the limit.\n Redis::set($cacheKey, (string) (time() + $retryAfter), 'EX', $retryAfter, 'NX');\n\n $this->log->warning('[Hubspot] Received 429 from API', [\n 'team_id' => $this->config->team_id,\n 'config_id' => $this->config->getId(),\n 'retry_after' => $retryAfter,\n 'reason' => $e->getMessage(),\n ]);\n\n throw new RateLimitException('Hubspot returned 429', $retryAfter, $e);\n }\n\n throw $e;\n }\n }\n\n private function getRateLimitCacheKey(): string\n {\n return sprintf('hubspot:ratelimit:config:%d', $this->config->getId());\n }\n\n private function isHubspotRateLimit(Throwable $e): bool\n {\n if ($e instanceof BadRequest\n || $e instanceof DealApiException\n || $e instanceof ContactApiException\n || $e instanceof CompanyApiException\n || $e instanceof \\GuzzleHttp\\Exception\\RequestException\n ) {\n return (int) $e->getCode() === 429;\n }\n\n return false;\n }\n\n private function parseRetryAfter(Throwable $e): int\n {\n if (method_exists($e, 'getResponseHeaders')) {\n $headers = $e->getResponseHeaders() ?: [];\n $value = $headers['Retry-After'] ?? $headers['retry-after'] ?? null;\n if (is_array($value)) {\n $value = $value[0] ?? null;\n }\n if (is_numeric($value)) {\n return (int) $value;\n }\n }\n\n $message = strtolower($e->getMessage());\n\n if (str_contains($message, 'daily')) {\n return 600;\n }\n if (str_contains($message, 'ten secondly')) {\n return 10;\n }\n if (str_contains($message, 'secondly')) {\n return 1;\n }\n\n $this->log->warning('[Hubspot] No retry-after header or known message, using default', [\n 'exception_class' => get_class($e),\n 'message' => $message,\n ]);\n\n return 10;\n }\n\n public function getMinimumApiVersion(): string\n {\n return self::MIN_API_VERSION;\n }\n\n public function getInstance(): Factory\n {\n return new Factory([\n 'key' => $this->accessToken,\n 'oauth2' => true,\n 'base_url' => $this->baseUrl,\n ]);\n }\n\n public function getNewInstance(): Discovery\n {\n return \\HubSpot\\Factory::createWithAccessToken($this->accessToken);\n }\n\n /**\n * Secondly and daily limits for Hubspot API\n *\n * Product Tier: Free & Starter | Professional & Enterprise | API add-on (any tier)\n * Burst: 100/10 seconds | 150/10 seconds | 200/10 seconds\n * Daily: 250,000 | 500,000 | 1,000,000\n *\n * Official documentation states: The search endpoints are rate limited to five requests per second.\n * Since with 5 RPS were still hitting secondly rate limits we lowered it to 4\n */\n public function getPaginatedData(array $payload, string $type, int $offset = 0): array\n {\n $total = 0;\n $lastId = null;\n $rows = [];\n foreach ($this->getPaginatedDataGenerator($payload, $type, $offset, $total, $lastId) as $row) {\n $rows[] = $row;\n }\n\n return ['results' => $rows, 'total' => $total, 'last_record' => $lastId];\n }\n\n /**\n * @throws HubspotException\n * @throws SocialAccountTokenInvalidException\n * @throws BadRequest\n */\n public function getPaginatedDataGenerator(\n array $payload,\n string $type,\n int $offset = 0,\n int &$total = 0,\n ?string &$lastRecordId = null\n ): \\Generator {\n return $this->paginationService->getPaginatedDataGenerator(\n $this,\n $payload,\n $type,\n $offset,\n $total,\n $lastRecordId\n );\n }\n\n /**\n * Execute a search request against HubSpot CRM objects with rate limiting.\n *\n * @param string $objectType The object type ('deals', 'companies', 'contacts', 'calls')\n * @param array<string, mixed> $payload The search payload with filters, sorts, properties, etc.\n *\n * @throws RateLimitException When rate limit is hit\n * @throws HubspotException On API errors\n *\n * @return array The search response with 'results', 'total', 'paging' keys\n */\n public function search(string $objectType, array $payload): array\n {\n $endpoint = self::BASE_URL . \"/crm/v3/objects/{$objectType}/search\";\n\n return $this->executeRequest(function () use ($endpoint, $payload) {\n $response = $this->getInstance()->getClient()->request('POST', $endpoint, ['json' => $payload]);\n\n return $response->toArray();\n });\n }\n\n /**\n * @throws DealApiException\n * @throws CrmException\n */\n public function getOpportunityById(string $crmId, array $fields): array\n {\n try {\n $deal = $this->getNewInstance()->crm()->deals()->basicApi()->getById(\n $crmId,\n implode(',', $fields),\n 'companies,contacts'\n );\n } catch (DealApiException $e) {\n $this->log->info('[Hubspot] Failed to fetch opportunity', [\n 'crm_id' => $crmId,\n 'reason' => $e->getMessage(),\n ]);\n\n throw $e;\n }\n\n if (! $deal instanceof DealWithAssociations) {\n throw new CrmException('Deal not found');\n }\n\n return [\n 'id' => $deal->getId(),\n 'properties' => $deal->getProperties(),\n 'associations' => $deal->getAssociations(),\n ];\n }\n\n /**\n * Generic batch read method for HubSpot objects\n *\n * @param string $objectType The object type ('deals', 'companies', 'contacts')\n * @param array<string> $crmIds Array of HubSpot object IDs (max 100)\n * @param array<string> $fields Array of property names to fetch\n *\n * @return array<string, array> Array keyed by CRM ID with object data\n */\n private function batchReadObjects(string $objectType, array $crmIds, array $fields): array\n {\n if (empty($crmIds)) {\n return [];\n }\n\n $this->validateBatchSize($objectType, $crmIds);\n $this->ensureValidToken();\n\n try {\n $batchConfig = $this->createBatchConfiguration($objectType);\n $batchReadRequest = $this->prepareBatchRequest($batchConfig, $crmIds, $fields);\n $response = $batchConfig['api']->read($batchReadRequest);\n\n $this->validateApiResponse($response, $objectType);\n\n $results = $this->processApiResults($response);\n $this->logBatchResults($objectType, $crmIds, $results);\n\n return $results;\n } catch (\\Throwable $e) {\n $this->handleBatchError($e, $objectType, $crmIds);\n }\n }\n\n private function validateBatchSize(string $objectType, array $crmIds): void\n {\n if (count($crmIds) > 100) {\n throw new \\InvalidArgumentException(\"Batch size cannot exceed 100 {$objectType}\");\n }\n }\n\n private function createBatchConfiguration(string $objectType): array\n {\n $configurations = [\n 'deals' => [\n 'batchReadRequest' => new \\HubSpot\\Client\\Crm\\Deals\\Model\\BatchReadInputSimplePublicObjectId(),\n 'inputClass' => \\HubSpot\\Client\\Crm\\Deals\\Model\\SimplePublicObjectId::class,\n 'api' => $this->getNewInstance()->crm()->deals()->batchApi(),\n ],\n 'companies' => [\n 'batchReadRequest' => new \\HubSpot\\Client\\Crm\\Companies\\Model\\BatchReadInputSimplePublicObjectId(),\n 'inputClass' => \\HubSpot\\Client\\Crm\\Companies\\Model\\SimplePublicObjectId::class,\n 'api' => $this->getNewInstance()->crm()->companies()->batchApi(),\n ],\n 'contacts' => [\n 'batchReadRequest' => new \\HubSpot\\Client\\Crm\\Contacts\\Model\\BatchReadInputSimplePublicObjectId(),\n 'inputClass' => \\HubSpot\\Client\\Crm\\Contacts\\Model\\SimplePublicObjectId::class,\n 'api' => $this->getNewInstance()->crm()->contacts()->batchApi(),\n ],\n ];\n\n if (! isset($configurations[$objectType])) {\n throw new \\InvalidArgumentException(\"Unsupported object type: {$objectType}\");\n }\n\n return $configurations[$objectType];\n }\n\n private function prepareBatchRequest(array $batchConfig, array $crmIds, array $fields): object\n {\n $batchReadRequest = $batchConfig['batchReadRequest'];\n $inputClass = $batchConfig['inputClass'];\n\n $inputs = array_map(function ($crmId) use ($inputClass) {\n $input = new $inputClass();\n $input->setId($crmId);\n\n return $input;\n }, $crmIds);\n\n $batchReadRequest->setInputs($inputs);\n $batchReadRequest->setProperties($fields);\n\n return $batchReadRequest;\n }\n\n private function validateApiResponse($response, string $objectType): void\n {\n if (! $response) {\n throw new CrmException(\"HubSpot API returned null response for {$objectType} batch read\");\n }\n }\n\n private function processApiResults($response): array\n {\n $results = [];\n $responseResults = $response->getResults();\n\n if ($responseResults) {\n foreach ($responseResults as $object) {\n if ($object && $object->getId()) {\n $results[$object->getId()] = [\n 'id' => $object->getId(),\n 'properties' => $object->getProperties() ?: [],\n ];\n }\n }\n }\n\n return $results;\n }\n\n private function logBatchResults(string $objectType, array $crmIds, array $results): void\n {\n $this->log->info(\"[HubSpot] Batch fetched {$objectType}\", [\n 'requested_count' => count($crmIds),\n 'returned_count' => count($results),\n 'crm_ids' => $crmIds,\n ]);\n }\n\n private function handleBatchError(\\Throwable $e, string $objectType, array $crmIds): void\n {\n $errorMessage = $e->getMessage() ?: 'Unknown error';\n $errorTrace = $e->getTraceAsString() ?: 'No trace available';\n\n $this->log->error(\"[HubSpot] Failed to batch fetch {$objectType}\", [\n 'crm_ids' => $crmIds,\n 'error' => $errorMessage,\n 'trace' => $errorTrace,\n ]);\n\n throw new CrmException(\"Failed to batch fetch {$objectType}: \" . $errorMessage);\n }\n\n /**\n * Batch read multiple opportunities by their CRM IDs\n *\n * @param array<string> $crmIds Array of HubSpot deal IDs (max 100)\n * @param array<string> $fields Array of property names to fetch\n *\n * @return array<string, array> Array keyed by CRM ID with opportunity data\n */\n public function getOpportunitiesByIds(array $crmIds, array $fields): array\n {\n return $this->batchReadObjects('deals', $crmIds, $fields);\n }\n\n /**\n * Batch read multiple companies by their CRM IDs\n *\n * @param array<string> $crmIds Array of HubSpot company IDs (max 100)\n * @param array<string> $fields Array of property names to fetch\n *\n * @return array<string, array> Array keyed by CRM ID with company data\n */\n public function getCompaniesByIds(array $crmIds, array $fields): array\n {\n return $this->batchReadObjects('companies', $crmIds, $fields);\n }\n\n /**\n * Batch read multiple contacts by their CRM IDs\n *\n * @param array<string> $crmIds Array of HubSpot contact IDs (max 100)\n * @param array<string> $fields Array of property names to fetch\n *\n * @return array<string, array> Array keyed by CRM ID with contact data\n */\n public function getContactsByIds(array $crmIds, array $fields): array\n {\n return $this->batchReadObjects('contacts', $crmIds, $fields);\n }\n\n /**\n * @throws CompanyApiException\n * @throws CrmException\n */\n public function getAccountById(string $crmId, array $fields): array\n {\n try {\n $company = $this->getNewInstance()->crm()->companies()->basicApi()->getById(\n $crmId,\n implode(',', $fields),\n );\n } catch (CompanyApiException $e) {\n $this->log->info('[Hubspot] Failed to fetch account', [\n 'crm_id' => $crmId,\n 'reason' => $e->getMessage(),\n ]);\n\n throw $e;\n }\n\n if (! $company instanceof CompaniesWithAssociations) {\n throw new CrmException('Account not found');\n }\n\n return [\n 'id' => $company->getId(),\n 'properties' => $company->getProperties(),\n ];\n }\n\n /**\n * @throws ContactApiException\n * @throws CrmException\n */\n public function getContactById(string $crmId, array $fields): array\n {\n try {\n $contact = $this->getNewInstance()->crm()->contacts()->basicApi()->getById(\n $crmId,\n implode(',', $fields)\n );\n } catch (ContactApiException $e) {\n $this->log->info('[Hubspot] Failed to fetch contact', [\n 'crm_id' => $crmId,\n 'reason' => $e->getMessage(),\n ]);\n\n throw $e;\n }\n\n if (! $contact instanceof ContactsWithAssociations) {\n throw new CrmException('Contact not found');\n }\n\n return [\n 'id' => $contact->getId(),\n 'properties' => $contact->getProperties(),\n ];\n }\n\n /**\n * This is email search request that Hubspot offers as GET (more generous quota)\n */\n public function getContactByEmail(string $email, array $fields = []): array\n {\n try {\n $contact = $this->getNewInstance()->crm()->contacts()->basicApi()->getById(\n $email,\n implode(',', $fields),\n null,\n false,\n 'email'\n );\n\n return [\n 'id' => $contact->getId(),\n 'properties' => $contact->getProperties(),\n ];\n } catch (ContactApiException $e) {\n $this->log->info('[Hubspot] Failed to fetch contact', [\n 'email' => $email,\n 'reason' => $e->getMessage(),\n ]);\n\n return [];\n }\n }\n\n /**\n * @throws CrmException\n */\n public function fetchProperty(string $objectType, string $propertyId): Property\n {\n $result = $this->getNewInstance()->crm()->properties()->coreApi()->getByName($objectType, $propertyId);\n\n if (! $result instanceof Property) {\n $this->log->error('[Hubspot] Failed to fetch property', [\n 'object_type' => $objectType,\n 'property_id' => $propertyId,\n 'reason' => $result->getMessage(),\n ]);\n\n throw new CrmException('Failed to fetch property');\n }\n\n return $result;\n }\n\n /**\n * @return array<CrmFieldOption>\n */\n public function fetchPropertyOptions(string $objectType, string $propertyId): array\n {\n /** @var array<CrmFieldOption> */\n return $this->fetchProperty($objectType, $propertyId)->getOptions();\n }\n\n /**\n * @return array<array{id:string, label:string, deleted:bool}>\n */\n public function fetchCallDispositions(): array\n {\n /** @var Response $response */\n $response = $this->getInstance()->engagements()->getCallDispositions();\n\n /**\n * @var array<array{\n * id:string,\n * label:string,\n * deleted: bool\n * }>\n */\n return $response->toArray();\n }\n\n /**\n * @return array<CrmFieldOption>\n */\n public function fetchOpportunityPipelineStages(): array\n {\n $stages = [];\n $apiResponse = $this->getNewInstance()->crm()->pipelines()->pipelinesApi()->getAll('deals');\n\n if ($apiResponse instanceof Error) {\n $this->log->error('[Hubspot] Failed to fetch opportunity pipelines', [\n 'reason' => $apiResponse->getMessage(),\n ]);\n\n return [];\n }\n\n foreach ($apiResponse->getResults() as $pipeline) {\n $pipelineStages = array_map(\n static function (PipelineStage $stage) {\n return [\n 'id' => $stage->getId(),\n 'label' => $stage->getLabel(),\n ];\n },\n $pipeline->getStages()\n );\n\n $stages = array_merge($stages, $pipelineStages);\n }\n\n return $stages;\n }\n\n public function fetchOpportunityPipelines(): array\n {\n $pipelines = [];\n\n try {\n $apiResponse = $this->makeRequest('/crm/v3/pipelines/deals');\n } catch (\\Exception $e) {\n $this->log->info('[Hubspot] Failed to fetch opportunity pipelines', [\n 'reason' => $e->getMessage(),\n ]);\n\n return [];\n }\n\n $response = $apiResponse->toArray();\n\n foreach ($response['results'] as $pipeline) {\n $pipelines[] = [\n 'id' => $pipeline['id'],\n 'label' => $pipeline['label'],\n ];\n }\n\n return $pipelines;\n }\n\n /**\n * @return array<CrmFieldOption>\n */\n public function fetchMeetingOutcomeFieldOptions(Field $field): array\n {\n return $field->getCrmProviderId() === 'meetingOutcome'\n ? $this->fetchMeetingOutcomeTypes()\n : $this->fetchCallActivityTypes();\n }\n\n public function fetchMeetingOutcomeTypes(): array\n {\n return $this->extractMeetingTypeOptions(\n 'https://api.hubapi.com/crm/v3/properties/meeting/hs_meeting_outcome'\n );\n }\n\n public function fetchCallActivityTypes(): array\n {\n return $this->extractMeetingTypeOptions(\n 'https://api.hubapi.com/crm/v3/properties/call/hs_activity_type'\n );\n }\n\n private function extractMeetingTypeOptions(string $endpoint): array\n {\n /** @var Response $response */\n $response = $this->getInstance()\n ->getClient()\n ->request('GET', $endpoint);\n\n /**\n * @var array<array{\n * value: string,\n * label: string,\n * displayOrder: int\n * }> $optionData\n */\n $optionData = $response->toArray()['options'] ?? [];\n\n $options = [];\n foreach ($optionData as $item) {\n $options[] = [\n 'id' => $item['value'],\n 'value' => $item['value'],\n 'label' => $item['label'],\n 'display_order' => $item['displayOrder'],\n ];\n }\n\n return $options;\n }\n\n /**\n * @return array<CrmFieldOption>\n */\n public function fetchDispositionFieldOptions(): array\n {\n $options = [];\n\n $dispositions = $this->fetchCallDispositions();\n\n foreach ($dispositions as $disposition) {\n if ($disposition['deleted'] !== false) {\n continue;\n }\n\n $option['value'] = $disposition['id'];\n $option['id'] = $disposition['id'];\n $option['label'] = $disposition['label'];\n\n $options[] = $option;\n }\n\n return $options;\n }\n\n /**\n * @return array<CrmFieldOption>\n */\n public function fetchOpportunityFieldOptions(Field $field): array\n {\n if ($field->isStageField()) {\n return $this->fetchOpportunityPipelineStages();\n }\n\n if ($field->isPipelineField()) {\n return $this->fetchOpportunityPipelines();\n }\n\n return $this->fetchPropertyOptions('deals', $field->getCrmProviderId());\n }\n\n /**\n * @throws BadRequest\n * @throws HubspotException\n */\n public function makeRequest(string $endpoint, $method = 'GET', $payload = [], ?string $queryString = null)\n {\n $endpoint = self::BASE_URL . $endpoint;\n\n if ($method === 'GET') {\n return $this->getInstance()->getClient()?->request(\n method: $method,\n endpoint: $endpoint,\n query_string: $queryString\n );\n } else {\n return $this->getInstance()->getClient()->request($method, $endpoint, [\n 'json' => ($payload),\n ]);\n }\n }\n\n /**\n * @throws BadRequest\n * @throws HubspotException\n */\n public function createMeeting(array $payload): Response\n {\n $endpoint = '/crm/v3/objects/meetings';\n\n return $this->makeRequest($endpoint, 'POST', $payload);\n }\n\n /**\n * @throws BadRequest\n * @throws HubspotException\n */\n public function updateMeeting(string $meetingId, array $payload): Response\n {\n $endpoint = '/crm/v3/objects/meetings/' . $meetingId;\n\n return $this->makeRequest($endpoint, 'PATCH', $payload);\n }\n\n /**\n * @throws \\Exception\n */\n public function createNote(\n string $body,\n string $ownerId,\n int $timestamp,\n string $objectId,\n NoteObject $noteObject\n ): ?string {\n try {\n $noteInput = new SimplePublicObjectInput([\n 'properties' => [\n 'hs_note_body' => $body,\n 'hubspot_owner_id' => $ownerId,\n 'hs_timestamp' => $timestamp,\n ],\n ]);\n\n // Create note\n $note = $this->getNewInstance()->crm()->objects()->basicApi()->create('note', $noteInput);\n\n $this->getNewInstance()->crm()->objects()->associationsApi()->create(\n 'note',\n $note->getId(),\n $this->getNoteObject($noteObject),\n $objectId,\n $this->getNoteAssociationType($noteObject),\n );\n\n return $note->getId();\n } catch (\\Exception $e) {\n $this->log->error('[Hubspot] Failed to create note', [\n 'objectId' => $objectId,\n 'noteObject' => $noteObject->getObjectType(),\n 'reason' => $e->getMessage(),\n ]);\n\n \\Sentry::captureException($e);\n }\n\n return null;\n }\n\n public function updateEngagement(string $objectId, array $engagement, array $metadata): void\n {\n $this->getInstance()->engagements()->update($objectId, $engagement, $metadata);\n }\n\n public function getEngagementData(string $engagementId): array\n {\n $engagement = $this->getInstance()->engagements()->get($engagementId);\n\n return $engagement->toArray();\n }\n\n public function createEngagement(array $engagement, array $associations, array $metadata): Response\n {\n return $this->getInstance()\n ->engagements()\n ->create($engagement, $associations, $metadata);\n }\n\n public function isUnauthorizedException(\\Exception $e): bool\n {\n // Check for specific HubSpot API exception types first\n if ($e instanceof BadRequest) {\n // BadRequest can contain 401 status codes\n return $e->getCode() === 401;\n }\n\n // Check for HTTP client exceptions with status codes\n if ($e instanceof \\GuzzleHttp\\Exception\\RequestException && $e->hasResponse()) {\n $response = $e->getResponse();\n if ($response !== null) {\n return $response->getStatusCode() === 401;\n }\n }\n\n // Check for Guzzle HTTP exceptions\n if ($e instanceof \\GuzzleHttp\\Exception\\ClientException) {\n return $e->getCode() === 401;\n }\n\n // Fallback to string matching as last resort, but be more specific\n $message = strtolower($e->getMessage());\n\n return str_contains($message, '401 unauthorized') ||\n str_contains($message, 'http 401') ||\n str_contains($message, 'status code 401') ||\n (preg_match('/\\b401\\b/', $message) && str_contains($message, 'unauthorized'));\n }\n\n /**\n * Validates and refreshes the access token if needed before API requests.\n * This ensures long-running processes don't fail due to token expiration.\n *\n * @throws SocialAccountTokenInvalidException\n */\n public function ensureValidToken(): void\n {\n if ($this->oauthAccount === null) {\n return;\n }\n\n $newToken = $this->tokenManager->ensureValidToken($this->oauthAccount);\n if ($newToken !== null) {\n $this->accessToken = $newToken;\n }\n }\n\n public function getConfig()\n {\n return $this->config;\n }\n\n // returns only active (archived=false)\n public function getOwners(): array\n {\n return $this->getNewInstance()->crm()->owners()->getAll();\n }\n\n /**\n * @param bool $archived\n *\n * @return array<Owner>|[]\n */\n public function getOwnersArchived(bool $archived = true): array\n {\n $endpoint = '/crm/v3/owners';\n $queryParams = [\n 'archived' => $archived ? 'true' : 'false',\n ];\n $queryString = http_build_query($queryParams);\n\n $owners = [];\n\n try {\n $response = $this->makeRequest(endpoint: $endpoint, queryString: $queryString);\n $responseData = $response?->toArray();\n\n foreach ($responseData['results'] as $result) {\n try {\n $owners[] = Owner::create($result);\n } catch (Throwable $e) {\n $this->log->error('[HubSpot] Failed to process owner data', [\n 'result' => $result,\n 'error' => $e->getMessage(),\n ]);\n\n continue;\n }\n }\n } catch (Throwable $e) {\n $this->log->error('HubSpot] Failed to fetch owners', [\n 'archived' => $archived,\n 'error' => $e->getMessage(),\n ]);\n\n return [];\n }\n\n return $owners;\n }\n\n public function getMeeting(string $engagementId): ObjectWithAssociations\n {\n return $this->getNewInstance()->crm()->objects()->basicApi()\n ->getById('meeting', $engagementId, null, 'contact,company,deal');\n }\n\n public function deleteEngagement(string $engagementId): void\n {\n $this->getInstance()->engagements()->delete((int) $engagementId);\n }\n\n public function getAssociationsData(array $ids, string $fromObject, string $toObject): array\n {\n $associationData = [];\n $idChunks = array_chunk($ids, self::ASSOCIATIONS_BATCH_SIZE_LIMIT);\n\n foreach ($idChunks as $idChunk) {\n try {\n $batchInput = new \\HubSpot\\Client\\Crm\\Associations\\Model\\BatchInputPublicObjectId();\n $batchInput->setInputs(array_map(function ($id) {\n $publicObjectId = new \\HubSpot\\Client\\Crm\\Associations\\Model\\PublicObjectId();\n $publicObjectId->setId($id);\n\n return $publicObjectId;\n }, $idChunk));\n\n $associatedObjectsData = $this\n ->getNewInstance()\n ->crm()\n ->associations()\n ->batchApi()\n ->read($fromObject, $toObject, $batchInput);\n\n if ($associatedObjectsData instanceof \\HubSpot\\Client\\Crm\\Associations\\Model\\BatchResponsePublicAssociationMulti) {\n foreach ($associatedObjectsData->getResults() as $association) {\n $from = $association->getFrom()->getId();\n $toAssociations = $association->getTo();\n\n if (! empty($toAssociations)) {\n $associationData[$from] = array_map(function ($item) {\n return $item->getId();\n }, $toAssociations);\n }\n }\n }\n } catch (\\Exception $e) {\n $this->log->error('[Hubspot] Failed to fetch associations', [\n 'from_object' => $fromObject,\n 'to_object' => $toObject,\n 'reason' => $e->getMessage(),\n ]);\n }\n }\n\n return $associationData;\n }\n\n /**\n * @throws \\Exception\n */\n private function getNoteAssociationType(NoteObject $noteObject): string\n {\n return match($noteObject) {\n NoteObject::Opportunity => 'note_to_deal',\n NoteObject::Lead, NoteObject::Contact => 'note_to_contact', // or 'note_to_lead' if your portal supports it\n NoteObject::Account => 'note_to_company',\n NoteObject::Call, NoteObject::Event => throw new \\Exception('Not supported'),\n };\n }\n\n /**\n * @throws \\Exception\n */\n private function getNoteObject(NoteObject $noteObject): string\n {\n return match($noteObject) {\n NoteObject::Opportunity => 'deal',\n NoteObject::Lead, NoteObject::Contact => 'contact',\n NoteObject::Account => 'company',\n NoteObject::Call, NoteObject::Event => throw new \\Exception('Not supported'),\n };\n }\n\n public function addAssociations(string $objectType, string $associationType, array $payload): Response\n {\n $endpoint = \"/crm/v4/associations/$objectType/$associationType/batch/create\";\n\n return $this->makeRequest($endpoint, 'POST', $payload);\n }\n\n public function removeAssociations(string $objectType, string $associationType, array $payload): Response\n {\n $endpoint = \"/crm/v4/associations/$objectType/$associationType/batch/archive\";\n\n return $this->makeRequest($endpoint, 'POST', $payload);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Hubspot;\n\nuse HubSpot\\Client\\Crm\\Deals\\ApiException as DealApiException;\nuse HubSpot\\Client\\Crm\\Contacts\\ApiException as ContactApiException;\nuse HubSpot\\Client\\Crm\\Companies\\ApiException as CompanyApiException;\nuse HubSpot\\Client\\Crm\\Contacts\\Model\\SimplePublicObjectWithAssociations as ContactsWithAssociations;\nuse HubSpot\\Client\\Crm\\Companies\\Model\\SimplePublicObjectWithAssociations as CompaniesWithAssociations;\nuse HubSpot\\Client\\Crm\\Deals\\Model\\SimplePublicObjectWithAssociations as DealWithAssociations;\nuse HubSpot\\Client\\Crm\\Objects\\Model\\SimplePublicObjectInput;\nuse HubSpot\\Client\\Crm\\Objects\\Model\\SimplePublicObjectWithAssociations as ObjectWithAssociations;\nuse HubSpot\\Client\\Crm\\Pipelines\\Model\\Error;\nuse HubSpot\\Client\\Crm\\Pipelines\\Model\\PipelineStage;\nuse HubSpot\\Client\\Crm\\Properties\\Model\\Property;\nuse HubSpot\\Discovery\\Discovery;\nuse Jiminny\\Exceptions\\CrmException;\nuse Jiminny\\Exceptions\\RateLimitException;\nuse Jiminny\\Exceptions\\SocialAccountTokenInvalidException;\nuse Jiminny\\Jobs\\Crm\\NoteObject;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Services\\Crm\\BaseClient;\nuse Jiminny\\Services\\Crm\\Hubspot\\DTO\\Response\\Owner;\nuse Jiminny\\Services\\SocialAccountService;\nuse SevenShores\\Hubspot\\Exceptions\\BadRequest;\nuse SevenShores\\Hubspot\\Exceptions\\HubspotException;\nuse SevenShores\\Hubspot\\Factory;\nuse SevenShores\\Hubspot\\Http\\Response;\nuse Jiminny\\Services\\Crm\\Hubspot\\Pagination\\HubspotPaginationService;\nuse Illuminate\\Support\\Facades\\Redis;\nuse Throwable;\n\n/**\n * @phpstan-type CrmFieldOption array{id:string, label:string, value?:string}\n */\nclass Client extends BaseClient implements HubspotClientInterface\n{\n public const string MIN_API_VERSION = '2';\n\n public const string BASE_URL = 'https://api.hubapi.com';\n\n public const int ASSOCIATIONS_BATCH_SIZE_LIMIT = 1000;\n\n private HubspotPaginationService $paginationService;\n private HubspotTokenManager $tokenManager;\n\n public function __construct(\n SocialAccountService $socialAccountService,\n HubspotPaginationService $paginationService,\n HubspotTokenManager $tokenManager\n ) {\n parent::__construct($socialAccountService);\n $this->paginationService = $paginationService;\n $this->tokenManager = $tokenManager;\n\n $this->setBaseUrl(self::BASE_URL);\n $this->setVersion(self::MIN_API_VERSION);\n }\n\n /**\n * Execute a HubSpot API call with rate limit handling.\n *\n * On a 429, stores the absolute expiry timestamp with SET NX (first writer wins).\n * This means all subsequent jobs that also receive 429 in the same burst do not\n * reset the TTL — the window is anchored to the first 429, not the last.\n * Readers compute the remaining wait from the stored timestamp, so jobs that check\n * the cache near expiry are not delayed longer than necessary.\n *\n * @template T\n *\n * @param callable(): T $apiCall The API call to execute\n *\n * @throws RateLimitException When rate limit is hit or cached rate limit is active\n *\n * @return T The result of the API call\n */\n private function executeRequest(callable $apiCall)\n {\n $cacheKey = $this->getRateLimitCacheKey();\n\n $cachedExpiresAt = Redis::get($cacheKey);\n if (is_string($cachedExpiresAt) && is_numeric($cachedExpiresAt)) {\n $remaining = max(1, (int) $cachedExpiresAt - time());\n\n throw new RateLimitException(\n 'Hubspot rate limit (cached circuit-breaker)',\n $remaining,\n );\n }\n\n try {\n return $apiCall();\n } catch (Throwable $e) {\n if ($this->isHubspotRateLimit($e)) {\n $retryAfter = $this->parseRetryAfter($e);\n\n // NX: only the first job to receive a 429 in this burst sets the key.\n // Subsequent 429s in the same burst leave the TTL untouched so the\n // window is not reset by every concurrent job hitting the limit.\n Redis::set($cacheKey, (string) (time() + $retryAfter), 'EX', $retryAfter, 'NX');\n\n $this->log->warning('[Hubspot] Received 429 from API', [\n 'team_id' => $this->config->team_id,\n 'config_id' => $this->config->getId(),\n 'retry_after' => $retryAfter,\n 'reason' => $e->getMessage(),\n ]);\n\n throw new RateLimitException('Hubspot returned 429', $retryAfter, $e);\n }\n\n throw $e;\n }\n }\n\n private function getRateLimitCacheKey(): string\n {\n return sprintf('hubspot:ratelimit:config:%d', $this->config->getId());\n }\n\n private function isHubspotRateLimit(Throwable $e): bool\n {\n if ($e instanceof BadRequest\n || $e instanceof DealApiException\n || $e instanceof ContactApiException\n || $e instanceof CompanyApiException\n || $e instanceof \\GuzzleHttp\\Exception\\RequestException\n ) {\n return (int) $e->getCode() === 429;\n }\n\n return false;\n }\n\n private function parseRetryAfter(Throwable $e): int\n {\n if (method_exists($e, 'getResponseHeaders')) {\n $headers = $e->getResponseHeaders() ?: [];\n $value = $headers['Retry-After'] ?? $headers['retry-after'] ?? null;\n if (is_array($value)) {\n $value = $value[0] ?? null;\n }\n if (is_numeric($value)) {\n return (int) $value;\n }\n }\n\n $message = strtolower($e->getMessage());\n\n if (str_contains($message, 'daily')) {\n return 600;\n }\n if (str_contains($message, 'ten secondly')) {\n return 10;\n }\n if (str_contains($message, 'secondly')) {\n return 1;\n }\n\n $this->log->warning('[Hubspot] No retry-after header or known message, using default', [\n 'exception_class' => get_class($e),\n 'message' => $message,\n ]);\n\n return 10;\n }\n\n public function getMinimumApiVersion(): string\n {\n return self::MIN_API_VERSION;\n }\n\n public function getInstance(): Factory\n {\n return new Factory([\n 'key' => $this->accessToken,\n 'oauth2' => true,\n 'base_url' => $this->baseUrl,\n ]);\n }\n\n public function getNewInstance(): Discovery\n {\n return \\HubSpot\\Factory::createWithAccessToken($this->accessToken);\n }\n\n /**\n * Secondly and daily limits for Hubspot API\n *\n * Product Tier: Free & Starter | Professional & Enterprise | API add-on (any tier)\n * Burst: 100/10 seconds | 150/10 seconds | 200/10 seconds\n * Daily: 250,000 | 500,000 | 1,000,000\n *\n * Official documentation states: The search endpoints are rate limited to five requests per second.\n * Since with 5 RPS were still hitting secondly rate limits we lowered it to 4\n */\n public function getPaginatedData(array $payload, string $type, int $offset = 0): array\n {\n $total = 0;\n $lastId = null;\n $rows = [];\n foreach ($this->getPaginatedDataGenerator($payload, $type, $offset, $total, $lastId) as $row) {\n $rows[] = $row;\n }\n\n return ['results' => $rows, 'total' => $total, 'last_record' => $lastId];\n }\n\n /**\n * @throws HubspotException\n * @throws SocialAccountTokenInvalidException\n * @throws BadRequest\n */\n public function getPaginatedDataGenerator(\n array $payload,\n string $type,\n int $offset = 0,\n int &$total = 0,\n ?string &$lastRecordId = null\n ): \\Generator {\n return $this->paginationService->getPaginatedDataGenerator(\n $this,\n $payload,\n $type,\n $offset,\n $total,\n $lastRecordId\n );\n }\n\n /**\n * Execute a search request against HubSpot CRM objects with rate limiting.\n *\n * @param string $objectType The object type ('deals', 'companies', 'contacts', 'calls')\n * @param array<string, mixed> $payload The search payload with filters, sorts, properties, etc.\n *\n * @throws RateLimitException When rate limit is hit\n * @throws HubspotException On API errors\n *\n * @return array The search response with 'results', 'total', 'paging' keys\n */\n public function search(string $objectType, array $payload): array\n {\n $endpoint = self::BASE_URL . \"/crm/v3/objects/{$objectType}/search\";\n\n return $this->executeRequest(function () use ($endpoint, $payload) {\n $response = $this->getInstance()->getClient()->request('POST', $endpoint, ['json' => $payload]);\n\n return $response->toArray();\n });\n }\n\n /**\n * @throws DealApiException\n * @throws CrmException\n */\n public function getOpportunityById(string $crmId, array $fields): array\n {\n try {\n $deal = $this->getNewInstance()->crm()->deals()->basicApi()->getById(\n $crmId,\n implode(',', $fields),\n 'companies,contacts'\n );\n } catch (DealApiException $e) {\n $this->log->info('[Hubspot] Failed to fetch opportunity', [\n 'crm_id' => $crmId,\n 'reason' => $e->getMessage(),\n ]);\n\n throw $e;\n }\n\n if (! $deal instanceof DealWithAssociations) {\n throw new CrmException('Deal not found');\n }\n\n return [\n 'id' => $deal->getId(),\n 'properties' => $deal->getProperties(),\n 'associations' => $deal->getAssociations(),\n ];\n }\n\n /**\n * Generic batch read method for HubSpot objects\n *\n * @param string $objectType The object type ('deals', 'companies', 'contacts')\n * @param array<string> $crmIds Array of HubSpot object IDs (max 100)\n * @param array<string> $fields Array of property names to fetch\n *\n * @return array<string, array> Array keyed by CRM ID with object data\n */\n private function batchReadObjects(string $objectType, array $crmIds, array $fields): array\n {\n if (empty($crmIds)) {\n return [];\n }\n\n $this->validateBatchSize($objectType, $crmIds);\n $this->ensureValidToken();\n\n try {\n $batchConfig = $this->createBatchConfiguration($objectType);\n $batchReadRequest = $this->prepareBatchRequest($batchConfig, $crmIds, $fields);\n $response = $batchConfig['api']->read($batchReadRequest);\n\n $this->validateApiResponse($response, $objectType);\n\n $results = $this->processApiResults($response);\n $this->logBatchResults($objectType, $crmIds, $results);\n\n return $results;\n } catch (\\Throwable $e) {\n $this->handleBatchError($e, $objectType, $crmIds);\n }\n }\n\n private function validateBatchSize(string $objectType, array $crmIds): void\n {\n if (count($crmIds) > 100) {\n throw new \\InvalidArgumentException(\"Batch size cannot exceed 100 {$objectType}\");\n }\n }\n\n private function createBatchConfiguration(string $objectType): array\n {\n $configurations = [\n 'deals' => [\n 'batchReadRequest' => new \\HubSpot\\Client\\Crm\\Deals\\Model\\BatchReadInputSimplePublicObjectId(),\n 'inputClass' => \\HubSpot\\Client\\Crm\\Deals\\Model\\SimplePublicObjectId::class,\n 'api' => $this->getNewInstance()->crm()->deals()->batchApi(),\n ],\n 'companies' => [\n 'batchReadRequest' => new \\HubSpot\\Client\\Crm\\Companies\\Model\\BatchReadInputSimplePublicObjectId(),\n 'inputClass' => \\HubSpot\\Client\\Crm\\Companies\\Model\\SimplePublicObjectId::class,\n 'api' => $this->getNewInstance()->crm()->companies()->batchApi(),\n ],\n 'contacts' => [\n 'batchReadRequest' => new \\HubSpot\\Client\\Crm\\Contacts\\Model\\BatchReadInputSimplePublicObjectId(),\n 'inputClass' => \\HubSpot\\Client\\Crm\\Contacts\\Model\\SimplePublicObjectId::class,\n 'api' => $this->getNewInstance()->crm()->contacts()->batchApi(),\n ],\n ];\n\n if (! isset($configurations[$objectType])) {\n throw new \\InvalidArgumentException(\"Unsupported object type: {$objectType}\");\n }\n\n return $configurations[$objectType];\n }\n\n private function prepareBatchRequest(array $batchConfig, array $crmIds, array $fields): object\n {\n $batchReadRequest = $batchConfig['batchReadRequest'];\n $inputClass = $batchConfig['inputClass'];\n\n $inputs = array_map(function ($crmId) use ($inputClass) {\n $input = new $inputClass();\n $input->setId($crmId);\n\n return $input;\n }, $crmIds);\n\n $batchReadRequest->setInputs($inputs);\n $batchReadRequest->setProperties($fields);\n\n return $batchReadRequest;\n }\n\n private function validateApiResponse($response, string $objectType): void\n {\n if (! $response) {\n throw new CrmException(\"HubSpot API returned null response for {$objectType} batch read\");\n }\n }\n\n private function processApiResults($response): array\n {\n $results = [];\n $responseResults = $response->getResults();\n\n if ($responseResults) {\n foreach ($responseResults as $object) {\n if ($object && $object->getId()) {\n $results[$object->getId()] = [\n 'id' => $object->getId(),\n 'properties' => $object->getProperties() ?: [],\n ];\n }\n }\n }\n\n return $results;\n }\n\n private function logBatchResults(string $objectType, array $crmIds, array $results): void\n {\n $this->log->info(\"[HubSpot] Batch fetched {$objectType}\", [\n 'requested_count' => count($crmIds),\n 'returned_count' => count($results),\n 'crm_ids' => $crmIds,\n ]);\n }\n\n private function handleBatchError(\\Throwable $e, string $objectType, array $crmIds): void\n {\n $errorMessage = $e->getMessage() ?: 'Unknown error';\n $errorTrace = $e->getTraceAsString() ?: 'No trace available';\n\n $this->log->error(\"[HubSpot] Failed to batch fetch {$objectType}\", [\n 'crm_ids' => $crmIds,\n 'error' => $errorMessage,\n 'trace' => $errorTrace,\n ]);\n\n throw new CrmException(\"Failed to batch fetch {$objectType}: \" . $errorMessage);\n }\n\n /**\n * Batch read multiple opportunities by their CRM IDs\n *\n * @param array<string> $crmIds Array of HubSpot deal IDs (max 100)\n * @param array<string> $fields Array of property names to fetch\n *\n * @return array<string, array> Array keyed by CRM ID with opportunity data\n */\n public function getOpportunitiesByIds(array $crmIds, array $fields): array\n {\n return $this->batchReadObjects('deals', $crmIds, $fields);\n }\n\n /**\n * Batch read multiple companies by their CRM IDs\n *\n * @param array<string> $crmIds Array of HubSpot company IDs (max 100)\n * @param array<string> $fields Array of property names to fetch\n *\n * @return array<string, array> Array keyed by CRM ID with company data\n */\n public function getCompaniesByIds(array $crmIds, array $fields): array\n {\n return $this->batchReadObjects('companies', $crmIds, $fields);\n }\n\n /**\n * Batch read multiple contacts by their CRM IDs\n *\n * @param array<string> $crmIds Array of HubSpot contact IDs (max 100)\n * @param array<string> $fields Array of property names to fetch\n *\n * @return array<string, array> Array keyed by CRM ID with contact data\n */\n public function getContactsByIds(array $crmIds, array $fields): array\n {\n return $this->batchReadObjects('contacts', $crmIds, $fields);\n }\n\n /**\n * @throws CompanyApiException\n * @throws CrmException\n */\n public function getAccountById(string $crmId, array $fields): array\n {\n try {\n $company = $this->getNewInstance()->crm()->companies()->basicApi()->getById(\n $crmId,\n implode(',', $fields),\n );\n } catch (CompanyApiException $e) {\n $this->log->info('[Hubspot] Failed to fetch account', [\n 'crm_id' => $crmId,\n 'reason' => $e->getMessage(),\n ]);\n\n throw $e;\n }\n\n if (! $company instanceof CompaniesWithAssociations) {\n throw new CrmException('Account not found');\n }\n\n return [\n 'id' => $company->getId(),\n 'properties' => $company->getProperties(),\n ];\n }\n\n /**\n * @throws ContactApiException\n * @throws CrmException\n */\n public function getContactById(string $crmId, array $fields): array\n {\n try {\n $contact = $this->getNewInstance()->crm()->contacts()->basicApi()->getById(\n $crmId,\n implode(',', $fields)\n );\n } catch (ContactApiException $e) {\n $this->log->info('[Hubspot] Failed to fetch contact', [\n 'crm_id' => $crmId,\n 'reason' => $e->getMessage(),\n ]);\n\n throw $e;\n }\n\n if (! $contact instanceof ContactsWithAssociations) {\n throw new CrmException('Contact not found');\n }\n\n return [\n 'id' => $contact->getId(),\n 'properties' => $contact->getProperties(),\n ];\n }\n\n /**\n * This is email search request that Hubspot offers as GET (more generous quota)\n */\n public function getContactByEmail(string $email, array $fields = []): array\n {\n try {\n $contact = $this->getNewInstance()->crm()->contacts()->basicApi()->getById(\n $email,\n implode(',', $fields),\n null,\n false,\n 'email'\n );\n\n return [\n 'id' => $contact->getId(),\n 'properties' => $contact->getProperties(),\n ];\n } catch (ContactApiException $e) {\n $this->log->info('[Hubspot] Failed to fetch contact', [\n 'email' => $email,\n 'reason' => $e->getMessage(),\n ]);\n\n return [];\n }\n }\n\n /**\n * @throws CrmException\n */\n public function fetchProperty(string $objectType, string $propertyId): Property\n {\n $result = $this->getNewInstance()->crm()->properties()->coreApi()->getByName($objectType, $propertyId);\n\n if (! $result instanceof Property) {\n $this->log->error('[Hubspot] Failed to fetch property', [\n 'object_type' => $objectType,\n 'property_id' => $propertyId,\n 'reason' => $result->getMessage(),\n ]);\n\n throw new CrmException('Failed to fetch property');\n }\n\n return $result;\n }\n\n /**\n * @return array<CrmFieldOption>\n */\n public function fetchPropertyOptions(string $objectType, string $propertyId): array\n {\n /** @var array<CrmFieldOption> */\n return $this->fetchProperty($objectType, $propertyId)->getOptions();\n }\n\n /**\n * @return array<array{id:string, label:string, deleted:bool}>\n */\n public function fetchCallDispositions(): array\n {\n /** @var Response $response */\n $response = $this->getInstance()->engagements()->getCallDispositions();\n\n /**\n * @var array<array{\n * id:string,\n * label:string,\n * deleted: bool\n * }>\n */\n return $response->toArray();\n }\n\n /**\n * @return array<CrmFieldOption>\n */\n public function fetchOpportunityPipelineStages(): array\n {\n $stages = [];\n $apiResponse = $this->getNewInstance()->crm()->pipelines()->pipelinesApi()->getAll('deals');\n\n if ($apiResponse instanceof Error) {\n $this->log->error('[Hubspot] Failed to fetch opportunity pipelines', [\n 'reason' => $apiResponse->getMessage(),\n ]);\n\n return [];\n }\n\n foreach ($apiResponse->getResults() as $pipeline) {\n $pipelineStages = array_map(\n static function (PipelineStage $stage) {\n return [\n 'id' => $stage->getId(),\n 'label' => $stage->getLabel(),\n ];\n },\n $pipeline->getStages()\n );\n\n $stages = array_merge($stages, $pipelineStages);\n }\n\n return $stages;\n }\n\n public function fetchOpportunityPipelines(): array\n {\n $pipelines = [];\n\n try {\n $apiResponse = $this->makeRequest('/crm/v3/pipelines/deals');\n } catch (\\Exception $e) {\n $this->log->info('[Hubspot] Failed to fetch opportunity pipelines', [\n 'reason' => $e->getMessage(),\n ]);\n\n return [];\n }\n\n $response = $apiResponse->toArray();\n\n foreach ($response['results'] as $pipeline) {\n $pipelines[] = [\n 'id' => $pipeline['id'],\n 'label' => $pipeline['label'],\n ];\n }\n\n return $pipelines;\n }\n\n /**\n * @return array<CrmFieldOption>\n */\n public function fetchMeetingOutcomeFieldOptions(Field $field): array\n {\n return $field->getCrmProviderId() === 'meetingOutcome'\n ? $this->fetchMeetingOutcomeTypes()\n : $this->fetchCallActivityTypes();\n }\n\n public function fetchMeetingOutcomeTypes(): array\n {\n return $this->extractMeetingTypeOptions(\n 'https://api.hubapi.com/crm/v3/properties/meeting/hs_meeting_outcome'\n );\n }\n\n public function fetchCallActivityTypes(): array\n {\n return $this->extractMeetingTypeOptions(\n 'https://api.hubapi.com/crm/v3/properties/call/hs_activity_type'\n );\n }\n\n private function extractMeetingTypeOptions(string $endpoint): array\n {\n /** @var Response $response */\n $response = $this->getInstance()\n ->getClient()\n ->request('GET', $endpoint);\n\n /**\n * @var array<array{\n * value: string,\n * label: string,\n * displayOrder: int\n * }> $optionData\n */\n $optionData = $response->toArray()['options'] ?? [];\n\n $options = [];\n foreach ($optionData as $item) {\n $options[] = [\n 'id' => $item['value'],\n 'value' => $item['value'],\n 'label' => $item['label'],\n 'display_order' => $item['displayOrder'],\n ];\n }\n\n return $options;\n }\n\n /**\n * @return array<CrmFieldOption>\n */\n public function fetchDispositionFieldOptions(): array\n {\n $options = [];\n\n $dispositions = $this->fetchCallDispositions();\n\n foreach ($dispositions as $disposition) {\n if ($disposition['deleted'] !== false) {\n continue;\n }\n\n $option['value'] = $disposition['id'];\n $option['id'] = $disposition['id'];\n $option['label'] = $disposition['label'];\n\n $options[] = $option;\n }\n\n return $options;\n }\n\n /**\n * @return array<CrmFieldOption>\n */\n public function fetchOpportunityFieldOptions(Field $field): array\n {\n if ($field->isStageField()) {\n return $this->fetchOpportunityPipelineStages();\n }\n\n if ($field->isPipelineField()) {\n return $this->fetchOpportunityPipelines();\n }\n\n return $this->fetchPropertyOptions('deals', $field->getCrmProviderId());\n }\n\n /**\n * @throws BadRequest\n * @throws HubspotException\n */\n public function makeRequest(string $endpoint, $method = 'GET', $payload = [], ?string $queryString = null)\n {\n $endpoint = self::BASE_URL . $endpoint;\n\n if ($method === 'GET') {\n return $this->getInstance()->getClient()?->request(\n method: $method,\n endpoint: $endpoint,\n query_string: $queryString\n );\n } else {\n return $this->getInstance()->getClient()->request($method, $endpoint, [\n 'json' => ($payload),\n ]);\n }\n }\n\n /**\n * @throws BadRequest\n * @throws HubspotException\n */\n public function createMeeting(array $payload): Response\n {\n $endpoint = '/crm/v3/objects/meetings';\n\n return $this->makeRequest($endpoint, 'POST', $payload);\n }\n\n /**\n * @throws BadRequest\n * @throws HubspotException\n */\n public function updateMeeting(string $meetingId, array $payload): Response\n {\n $endpoint = '/crm/v3/objects/meetings/' . $meetingId;\n\n return $this->makeRequest($endpoint, 'PATCH', $payload);\n }\n\n /**\n * @throws \\Exception\n */\n public function createNote(\n string $body,\n string $ownerId,\n int $timestamp,\n string $objectId,\n NoteObject $noteObject\n ): ?string {\n try {\n $noteInput = new SimplePublicObjectInput([\n 'properties' => [\n 'hs_note_body' => $body,\n 'hubspot_owner_id' => $ownerId,\n 'hs_timestamp' => $timestamp,\n ],\n ]);\n\n // Create note\n $note = $this->getNewInstance()->crm()->objects()->basicApi()->create('note', $noteInput);\n\n $this->getNewInstance()->crm()->objects()->associationsApi()->create(\n 'note',\n $note->getId(),\n $this->getNoteObject($noteObject),\n $objectId,\n $this->getNoteAssociationType($noteObject),\n );\n\n return $note->getId();\n } catch (\\Exception $e) {\n $this->log->error('[Hubspot] Failed to create note', [\n 'objectId' => $objectId,\n 'noteObject' => $noteObject->getObjectType(),\n 'reason' => $e->getMessage(),\n ]);\n\n \\Sentry::captureException($e);\n }\n\n return null;\n }\n\n public function updateEngagement(string $objectId, array $engagement, array $metadata): void\n {\n $this->getInstance()->engagements()->update($objectId, $engagement, $metadata);\n }\n\n public function getEngagementData(string $engagementId): array\n {\n $engagement = $this->getInstance()->engagements()->get($engagementId);\n\n return $engagement->toArray();\n }\n\n public function createEngagement(array $engagement, array $associations, array $metadata): Response\n {\n return $this->getInstance()\n ->engagements()\n ->create($engagement, $associations, $metadata);\n }\n\n public function isUnauthorizedException(\\Exception $e): bool\n {\n // Check for specific HubSpot API exception types first\n if ($e instanceof BadRequest) {\n // BadRequest can contain 401 status codes\n return $e->getCode() === 401;\n }\n\n // Check for HTTP client exceptions with status codes\n if ($e instanceof \\GuzzleHttp\\Exception\\RequestException && $e->hasResponse()) {\n $response = $e->getResponse();\n if ($response !== null) {\n return $response->getStatusCode() === 401;\n }\n }\n\n // Check for Guzzle HTTP exceptions\n if ($e instanceof \\GuzzleHttp\\Exception\\ClientException) {\n return $e->getCode() === 401;\n }\n\n // Fallback to string matching as last resort, but be more specific\n $message = strtolower($e->getMessage());\n\n return str_contains($message, '401 unauthorized') ||\n str_contains($message, 'http 401') ||\n str_contains($message, 'status code 401') ||\n (preg_match('/\\b401\\b/', $message) && str_contains($message, 'unauthorized'));\n }\n\n /**\n * Validates and refreshes the access token if needed before API requests.\n * This ensures long-running processes don't fail due to token expiration.\n *\n * @throws SocialAccountTokenInvalidException\n */\n public function ensureValidToken(): void\n {\n if ($this->oauthAccount === null) {\n return;\n }\n\n $newToken = $this->tokenManager->ensureValidToken($this->oauthAccount);\n if ($newToken !== null) {\n $this->accessToken = $newToken;\n }\n }\n\n public function getConfig()\n {\n return $this->config;\n }\n\n // returns only active (archived=false)\n public function getOwners(): array\n {\n return $this->getNewInstance()->crm()->owners()->getAll();\n }\n\n /**\n * @param bool $archived\n *\n * @return array<Owner>|[]\n */\n public function getOwnersArchived(bool $archived = true): array\n {\n $endpoint = '/crm/v3/owners';\n $queryParams = [\n 'archived' => $archived ? 'true' : 'false',\n ];\n $queryString = http_build_query($queryParams);\n\n $owners = [];\n\n try {\n $response = $this->makeRequest(endpoint: $endpoint, queryString: $queryString);\n $responseData = $response?->toArray();\n\n foreach ($responseData['results'] as $result) {\n try {\n $owners[] = Owner::create($result);\n } catch (Throwable $e) {\n $this->log->error('[HubSpot] Failed to process owner data', [\n 'result' => $result,\n 'error' => $e->getMessage(),\n ]);\n\n continue;\n }\n }\n } catch (Throwable $e) {\n $this->log->error('HubSpot] Failed to fetch owners', [\n 'archived' => $archived,\n 'error' => $e->getMessage(),\n ]);\n\n return [];\n }\n\n return $owners;\n }\n\n public function getMeeting(string $engagementId): ObjectWithAssociations\n {\n return $this->getNewInstance()->crm()->objects()->basicApi()\n ->getById('meeting', $engagementId, null, 'contact,company,deal');\n }\n\n public function deleteEngagement(string $engagementId): void\n {\n $this->getInstance()->engagements()->delete((int) $engagementId);\n }\n\n public function getAssociationsData(array $ids, string $fromObject, string $toObject): array\n {\n $associationData = [];\n $idChunks = array_chunk($ids, self::ASSOCIATIONS_BATCH_SIZE_LIMIT);\n\n foreach ($idChunks as $idChunk) {\n try {\n $batchInput = new \\HubSpot\\Client\\Crm\\Associations\\Model\\BatchInputPublicObjectId();\n $batchInput->setInputs(array_map(function ($id) {\n $publicObjectId = new \\HubSpot\\Client\\Crm\\Associations\\Model\\PublicObjectId();\n $publicObjectId->setId($id);\n\n return $publicObjectId;\n }, $idChunk));\n\n $associatedObjectsData = $this\n ->getNewInstance()\n ->crm()\n ->associations()\n ->batchApi()\n ->read($fromObject, $toObject, $batchInput);\n\n if ($associatedObjectsData instanceof \\HubSpot\\Client\\Crm\\Associations\\Model\\BatchResponsePublicAssociationMulti) {\n foreach ($associatedObjectsData->getResults() as $association) {\n $from = $association->getFrom()->getId();\n $toAssociations = $association->getTo();\n\n if (! empty($toAssociations)) {\n $associationData[$from] = array_map(function ($item) {\n return $item->getId();\n }, $toAssociations);\n }\n }\n }\n } catch (\\Exception $e) {\n $this->log->error('[Hubspot] Failed to fetch associations', [\n 'from_object' => $fromObject,\n 'to_object' => $toObject,\n 'reason' => $e->getMessage(),\n ]);\n }\n }\n\n return $associationData;\n }\n\n /**\n * @throws \\Exception\n */\n private function getNoteAssociationType(NoteObject $noteObject): string\n {\n return match($noteObject) {\n NoteObject::Opportunity => 'note_to_deal',\n NoteObject::Lead, NoteObject::Contact => 'note_to_contact', // or 'note_to_lead' if your portal supports it\n NoteObject::Account => 'note_to_company',\n NoteObject::Call, NoteObject::Event => throw new \\Exception('Not supported'),\n };\n }\n\n /**\n * @throws \\Exception\n */\n private function getNoteObject(NoteObject $noteObject): string\n {\n return match($noteObject) {\n NoteObject::Opportunity => 'deal',\n NoteObject::Lead, NoteObject::Contact => 'contact',\n NoteObject::Account => 'company',\n NoteObject::Call, NoteObject::Event => throw new \\Exception('Not supported'),\n };\n }\n\n public function addAssociations(string $objectType, string $associationType, array $payload): Response\n {\n $endpoint = \"/crm/v4/associations/$objectType/$associationType/batch/create\";\n\n return $this->makeRequest($endpoint, 'POST', $payload);\n }\n\n public function removeAssociations(string $objectType, string $associationType, array $payload): Response\n {\n $endpoint = \"/crm/v4/associations/$objectType/$associationType/batch/archive\";\n\n return $this->makeRequest($endpoint, 'POST', $payload);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"bounds":{"left":0.41589096,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"bounds":{"left":0.4245346,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"bounds":{"left":0.43550533,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"bounds":{"left":0.44414893,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"bounds":{"left":0.45279256,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"bounds":{"left":0.4637633,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"bounds":{"left":0.47473404,"top":0.09896249,"width":0.024268618,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"bounds":{"left":0.5013298,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"bounds":{"left":0.51230055,"top":0.09896249,"width":0.029587766,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
7844122297473728914
|
5225835645296838756
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
#12121 on JY-20963-fix-im Project: faVsco.js, menu
#12121 on JY-20963-fix-import-on-deleted-entity, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
1
2
69
3
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Hubspot;
use HubSpot\Client\Crm\Deals\ApiException as DealApiException;
use HubSpot\Client\Crm\Contacts\ApiException as ContactApiException;
use HubSpot\Client\Crm\Companies\ApiException as CompanyApiException;
use HubSpot\Client\Crm\Contacts\Model\SimplePublicObjectWithAssociations as ContactsWithAssociations;
use HubSpot\Client\Crm\Companies\Model\SimplePublicObjectWithAssociations as CompaniesWithAssociations;
use HubSpot\Client\Crm\Deals\Model\SimplePublicObjectWithAssociations as DealWithAssociations;
use HubSpot\Client\Crm\Objects\Model\SimplePublicObjectInput;
use HubSpot\Client\Crm\Objects\Model\SimplePublicObjectWithAssociations as ObjectWithAssociations;
use HubSpot\Client\Crm\Pipelines\Model\Error;
use HubSpot\Client\Crm\Pipelines\Model\PipelineStage;
use HubSpot\Client\Crm\Properties\Model\Property;
use HubSpot\Discovery\Discovery;
use Jiminny\Exceptions\CrmException;
use Jiminny\Exceptions\RateLimitException;
use Jiminny\Exceptions\SocialAccountTokenInvalidException;
use Jiminny\Jobs\Crm\NoteObject;
use Jiminny\Models\Crm\Field;
use Jiminny\Services\Crm\BaseClient;
use Jiminny\Services\Crm\Hubspot\DTO\Response\Owner;
use Jiminny\Services\SocialAccountService;
use SevenShores\Hubspot\Exceptions\BadRequest;
use SevenShores\Hubspot\Exceptions\HubspotException;
use SevenShores\Hubspot\Factory;
use SevenShores\Hubspot\Http\Response;
use Jiminny\Services\Crm\Hubspot\Pagination\HubspotPaginationService;
use Illuminate\Support\Facades\Redis;
use Throwable;
/**
* @phpstan-type CrmFieldOption array{id:string, label:string, value?:string}
*/
class Client extends BaseClient implements HubspotClientInterface
{
public const string MIN_API_VERSION = '2';
public const string BASE_URL = '[URL_WITH_CREDENTIALS] T
*
* @param callable(): T $apiCall The API call to execute
*
* @throws RateLimitException When rate limit is hit or cached rate limit is active
*
* @return T The result of the API call
*/
private function executeRequest(callable $apiCall)
{
$cacheKey = $this->getRateLimitCacheKey();
$cachedExpiresAt = Redis::get($cacheKey);
if (is_string($cachedExpiresAt) && is_numeric($cachedExpiresAt)) {
$remaining = max(1, (int) $cachedExpiresAt - time());
throw new RateLimitException(
'Hubspot rate limit (cached circuit-breaker)',
$remaining,
);
}
try {
return $apiCall();
} catch (Throwable $e) {
if ($this->isHubspotRateLimit($e)) {
$retryAfter = $this->parseRetryAfter($e);
// NX: only the first job to receive a 429 in this burst sets the key.
// Subsequent 429s in the same burst leave the TTL untouched so the
// window is not reset by every concurrent job hitting the limit.
Redis::set($cacheKey, (string) (time() + $retryAfter), 'EX', $retryAfter, 'NX');
$this->log->warning('[Hubspot] Received 429 from API', [
'team_id' => $this->config->team_id,
'config_id' => $this->config->getId(),
'retry_after' => $retryAfter,
'reason' => $e->getMessage(),
]);
throw new RateLimitException('Hubspot returned 429', $retryAfter, $e);
}
throw $e;
}
}
private function getRateLimitCacheKey(): string
{
return sprintf('hubspot:ratelimit:config:%d', $this->config->getId());
}
private function isHubspotRateLimit(Throwable $e): bool
{
if ($e instanceof BadRequest
|| $e instanceof DealApiException
|| $e instanceof ContactApiException
|| $e instanceof CompanyApiException
|| $e instanceof \GuzzleHttp\Exception\RequestException
) {
return (int) $e->getCode() === 429;
}
return false;
}
private function parseRetryAfter(Throwable $e): int
{
if (method_exists($e, 'getResponseHeaders')) {
$headers = $e->getResponseHeaders() ?: [];
$value = $headers['Retry-After'] ?? $headers['retry-after'] ?? null;
if (is_array($value)) {
$value = $value[0] ?? null;
}
if (is_numeric($value)) {
return (int) $value;
}
}
$message = strtolower($e->getMessage());
if (str_contains($message, 'daily')) {
return 600;
}
if (str_contains($message, 'ten secondly')) {
return 10;
}
if (str_contains($message, 'secondly')) {
return 1;
}
$this->log->warning('[Hubspot] No retry-after header or known message, using default', [
'exception_class' => get_class($e),
'message' => $message,
]);
return 10;
}
public function getMinimumApiVersion(): string
{
return self::MIN_API_VERSION;
}
public function getInstance(): Factory
{
return new Factory([
'key' => $this->accessToken,
'oauth2' => true,
'base_url' => $this->baseUrl,
]);
}
public function getNewInstance(): Discovery
{
return \HubSpot\Factory::createWithAccessToken($this->accessToken);
}
/**
* Secondly and daily limits for Hubspot API
*
* Product Tier: Free & Starter | Professional & Enterprise | API add-on (any tier)
* Burst: 100/10 seconds | 150/10 seconds | 200/10 seconds
* Daily: 250,000 | 500,000 | 1,000,000
*
* Official documentation states: The search endpoints are rate limited to five requests per second.
* Since with 5 RPS were still hitting secondly rate limits we lowered it to 4
*/
public function getPaginatedData(array $payload, string $type, int $offset = 0): array
{
$total = 0;
$lastId = null;
$rows = [];
foreach ($this->getPaginatedDataGenerator($payload, $type, $offset, $total, $lastId) as $row) {
$rows[] = $row;
}
return ['results' => $rows, 'total' => $total, 'last_record' => $lastId];
}
/**
* @throws HubspotException
* @throws SocialAccountTokenInvalidException
* @throws BadRequest
*/
public function getPaginatedDataGenerator(
array $payload,
string $type,
int $offset = 0,
int &$total = 0,
?string &$lastRecordId = null
): \Generator {
return $this->paginationService->getPaginatedDataGenerator(
$this,
$payload,
$type,
$offset,
$total,
$lastRecordId
);
}
/**
* Execute a search request against HubSpot CRM objects with rate limiting.
*
* @param string $objectType The object type ('deals', 'companies', 'contacts', 'calls')
* @param array<string, mixed> $payload The search payload with filters, sorts, properties, etc.
*
* @throws RateLimitException When rate limit is hit
* @throws HubspotException On API errors
*
* @return array The search response with 'results', 'total', 'paging' keys
*/
public function search(string $objectType, array $payload): array
{
$endpoint = self::BASE_URL . "/crm/v3/objects/{$objectType}/search";
return $this->executeRequest(function () use ($endpoint, $payload) {
$response = $this->getInstance()->getClient()->request('POST', $endpoint, ['json' => $payload]);
return $response->toArray();
});
}
/**
* @throws DealApiException
* @throws CrmException
*/
public function getOpportunityById(string $crmId, array $fields): array
{
try {
$deal = $this->getNewInstance()->crm()->deals()->basicApi()->getById(
$crmId,
implode(',', $fields),
'companies,contacts'
);
} catch (DealApiException $e) {
$this->log->info('[Hubspot] Failed to fetch opportunity', [
'crm_id' => $crmId,
'reason' => $e->getMessage(),
]);
throw $e;
}
if (! $deal instanceof DealWithAssociations) {
throw new CrmException('Deal not found');
}
return [
'id' => $deal->getId(),
'properties' => $deal->getProperties(),
'associations' => $deal->getAssociations(),
];
}
/**
* Generic batch read method for HubSpot objects
*
* @param string $objectType The object type ('deals', 'companies', 'contacts')
* @param array<string> $crmIds Array of HubSpot object IDs (max 100)
* @param array<string> $fields Array of property names to fetch
*
* @return array<string, array> Array keyed by CRM ID with object data
*/
private function batchReadObjects(string $objectType, array $crmIds, array $fields): array
{
if (empty($crmIds)) {
return [];
}
$this->validateBatchSize($objectType, $crmIds);
$this->ensureValidToken();
try {
$batchConfig = $this->createBatchConfiguration($objectType);
$batchReadRequest = $this->prepareBatchRequest($batchConfig, $crmIds, $fields);
$response = $batchConfig['api']->read($batchReadRequest);
$this->validateApiResponse($response, $objectType);
$results = $this->processApiResults($response);
$this->logBatchResults($objectType, $crmIds, $results);
return $results;
} catch (\Throwable $e) {
$this->handleBatchError($e, $objectType, $crmIds);
}
}
private function validateBatchSize(string $objectType, array $crmIds): void
{
if (count($crmIds) > 100) {
throw new \InvalidArgumentException("Batch size cannot exceed 100 {$objectType}");
}
}
private function createBatchConfiguration(string $objectType): array
{
$configurations = [
'deals' => [
'batchReadRequest' => new \HubSpot\Client\Crm\Deals\Model\BatchReadInputSimplePublicObjectId(),
'inputClass' => \HubSpot\Client\Crm\Deals\Model\SimplePublicObjectId::class,
'api' => $this->getNewInstance()->crm()->deals()->batchApi(),
],
'companies' => [
'batchReadRequest' => new \HubSpot\Client\Crm\Companies\Model\BatchReadInputSimplePublicObjectId(),
'inputClass' => \HubSpot\Client\Crm\Companies\Model\SimplePublicObjectId::class,
'api' => $this->getNewInstance()->crm()->companies()->batchApi(),
],
'contacts' => [
'batchReadRequest' => new \HubSpot\Client\Crm\Contacts\Model\BatchReadInputSimplePublicObjectId(),
'inputClass' => \HubSpot\Client\Crm\Contacts\Model\SimplePublicObjectId::class,
'api' => $this->getNewInstance()->crm()->contacts()->batchApi(),
],
];
if (! isset($configurations[$objectType])) {
throw new \InvalidArgumentException("Unsupported object type: {$objectType}");
}
return $configurations[$objectType];
}
private function prepareBatchRequest(array $batchConfig, array $crmIds, array $fields): object
{
$batchReadRequest = $batchConfig['batchReadRequest'];
$inputClass = $batchConfig['inputClass'];
$inputs = array_map(function ($crmId) use ($inputClass) {
$input = new $inputClass();
$input->setId($crmId);
return $input;
}, $crmIds);
$batchReadRequest->setInputs($inputs);
$batchReadRequest->setProperties($fields);
return $batchReadRequest;
}
private function validateApiResponse($response, string $objectType): void
{
if (! $response) {
throw new CrmException("HubSpot API returned null response for {$objectType} batch read");
}
}
private function processApiResults($response): array
{
$results = [];
$responseResults = $response->getResults();
if ($responseResults) {
foreach ($responseResults as $object) {
if ($object && $object->getId()) {
$results[$object->getId()] = [
'id' => $object->getId(),
'properties' => $object->getProperties() ?: [],
];
}
}
}
return $results;
}
private function logBatchResults(string $objectType, array $crmIds, array $results): void
{
$this->log->info("[HubSpot] Batch fetched {$objectType}", [
'requested_count' => count($crmIds),
'returned_count' => count($results),
'crm_ids' => $crmIds,
]);
}
private function handleBatchError(\Throwable $e, string $objectType, array $crmIds): void
{
$errorMessage = $e->getMessage() ?: 'Unknown error';
$errorTrace = $e->getTraceAsString() ?: 'No trace available';
$this->log->error("[HubSpot] Failed to batch fetch {$objectType}", [
'crm_ids' => $crmIds,
'error' => $errorMessage,
'trace' => $errorTrace,
]);
throw new CrmException("Failed to batch fetch {$objectType}: " . $errorMessage);
}
/**
* Batch read multiple opportunities by their CRM IDs
*
* @param array<string> $crmIds Array of HubSpot deal IDs (max 100)
* @param array<string> $fields Array of property names to fetch
*
* @return array<string, array> Array keyed by CRM ID with opportunity data
*/
public function getOpportunitiesByIds(array $crmIds, array $fields): array
{
return $this->batchReadObjects('deals', $crmIds, $fields);
}
/**
* Batch read multiple companies by their CRM IDs
*
* @param array<string> $crmIds Array of HubSpot company IDs (max 100)
* @param array<string> $fields Array of property names to fetch
*
* @return array<string, array> Array keyed by CRM ID with company data
*/
public function getCompaniesByIds(array $crmIds, array $fields): array
{
return $this->batchReadObjects('companies', $crmIds, $fields);
}
/**
* Batch read multiple contacts by their CRM IDs
*
* @param array<string> $crmIds Array of HubSpot contact IDs (max 100)
* @param array<string> $fields Array of property names to fetch
*
* @return array<string, array> Array keyed by CRM ID with contact data
*/
public function getContactsByIds(array $crmIds, array $fields): array
{
return $this->batchReadObjects('contacts', $crmIds, $fields);
}
/**
* @throws CompanyApiException
* @throws CrmException
*/
public function getAccountById(string $crmId, array $fields): array
{
try {
$company = $this->getNewInstance()->crm()->companies()->basicApi()->getById(
$crmId,
implode(',', $fields),
);
} catch (CompanyApiException $e) {
$this->log->info('[Hubspot] Failed to fetch account', [
'crm_id' => $crmId,
'reason' => $e->getMessage(),
]);
throw $e;
}
if (! $company instanceof CompaniesWithAssociations) {
throw new CrmException('Account not found');
}
return [
'id' => $company->getId(),
'properties' => $company->getProperties(),
];
}
/**
* @throws ContactApiException
* @throws CrmException
*/
public function getContactById(string $crmId, array $fields): array
{
try {
$contact = $this->getNewInstance()->crm()->contacts()->basicApi()->getById(
$crmId,
implode(',', $fields)
);
} catch (ContactApiException $e) {
$this->log->info('[Hubspot] Failed to fetch contact', [
'crm_id' => $crmId,
'reason' => $e->getMessage(),
]);
throw $e;
}
if (! $contact instanceof ContactsWithAssociations) {
throw new CrmException('Contact not found');
}
return [
'id' => $contact->getId(),
'properties' => $contact->getProperties(),
];
}
/**
* This is email search request that Hubspot offers as GET (more generous quota)
*/
public function getContactByEmail(string $email, array $fields = []): array
{
try {
$contact = $this->getNewInstance()->crm()->contacts()->basicApi()->getById(
$email,
implode(',', $fields),
null,
false,
'email'
);
return [
'id' => $contact->getId(),
'properties' => $contact->getProperties(),
];
} catch (ContactApiException $e) {
$this->log->info('[Hubspot] Failed to fetch contact', [
'email' => $email,
'reason' => $e->getMessage(),
]);
return [];
}
}
/**
* @throws CrmException
*/
public function fetchProperty(string $objectType, string $propertyId): Property
{
$result = $this->getNewInstance()->crm()->properties()->coreApi()->getByName($objectType, $propertyId);
if (! $result instanceof Property) {
$this->log->error('[Hubspot] Failed to fetch property', [
'object_type' => $objectType,
'property_id' => $propertyId,
'reason' => $result->getMessage(),
]);
throw new CrmException('Failed to fetch property');
}
return $result;
}
/**
* @return array<CrmFieldOption>
*/
public function fetchPropertyOptions(string $objectType, string $propertyId): array
{
/** @var array<CrmFieldOption> */
return $this->fetchProperty($objectType, $propertyId)->getOptions();
}
/**
* @return array<array{id:string, label:string, deleted:bool}>
*/
public function fetchCallDispositions(): array
{
/** @var Response $response */
$response = $this->getInstance()->engagements()->getCallDispositions();
/**
* @var array<array{
* id:string,
* label:string,
* deleted: bool
* }>
*/
return $response->toArray();
}
/**
* @return array<CrmFieldOption>
*/
public function fetchOpportunityPipelineStages(): array
{
$stages = [];
$apiResponse = $this->getNewInstance()->crm()->pipelines()->pipelinesApi()->getAll('deals');
if ($apiResponse instanceof Error) {
$this->log->error('[Hubspot] Failed to fetch opportunity pipelines', [
'reason' => $apiResponse->getMessage(),
]);
return [];
}
foreach ($apiResponse->getResults() as $pipeline) {
$pipelineStages = array_map(
static function (PipelineStage $stage) {
return [
'id' => $stage->getId(),
'label' => $stage->getLabel(),
];
},
$pipeline->getStages()
);
$stages = array_merge($stages, $pipelineStages);
}
return $stages;
}
public function fetchOpportunityPipelines(): array
{
$pipelines = [];
try {
$apiResponse = $this->makeRequest('/crm/v3/pipelines/deals');
} catch (\Exception $e) {
$this->log->info('[Hubspot] Failed to fetch opportunity pipelines', [
'reason' => $e->getMessage(),
]);
return [];
}
$response = $apiResponse->toArray();
foreach ($response['results'] as $pipeline) {
$pipelines[] = [
'id' => $pipeline['id'],
'label' => $pipeline['label'],
];
}
return $pipelines;
}
/**
* @return array<CrmFieldOption>
*/
public function fetchMeetingOutcomeFieldOptions(Field $field): array
{
return $field->getCrmProviderId() === 'meetingOutcome'
? $this->fetchMeetingOutcomeTypes()
: $this->fetchCallActivityTypes();
}
public function fetchMeetingOutcomeTypes(): array
{
return $this->extractMeetingTypeOptions(
'[URL_WITH_CREDENTIALS] Response $response */
$response = $this->getInstance()
->getClient()
->request('GET', $endpoint);
/**
* @var array<array{
* value: string,
* label: string,
* displayOrder: int
* }> $optionData
*/
$optionData = $response->toArray()['options'] ?? [];
$options = [];
foreach ($optionData as $item) {
$options[] = [
'id' => $item['value'],
'value' => $item['value'],
'label' => $item['label'],
'display_order' => $item['displayOrder'],
];
}
return $options;
}
/**
* @return array<CrmFieldOption>
*/
public function fetchDispositionFieldOptions(): array
{
$options = [];
$dispositions = $this->fetchCallDispositions();
foreach ($dispositions as $disposition) {
if ($disposition['deleted'] !== false) {
continue;
}
$option['value'] = $disposition['id'];
$option['id'] = $disposition['id'];
$option['label'] = $disposition['label'];
$options[] = $option;
}
return $options;
}
/**
* @return array<CrmFieldOption>
*/
public function fetchOpportunityFieldOptions(Field $field): array
{
if ($field->isStageField()) {
return $this->fetchOpportunityPipelineStages();
}
if ($field->isPipelineField()) {
return $this->fetchOpportunityPipelines();
}
return $this->fetchPropertyOptions('deals', $field->getCrmProviderId());
}
/**
* @throws BadRequest
* @throws HubspotException
*/
public function makeRequest(string $endpoint, $method = 'GET', $payload = [], ?string $queryString = null)
{
$endpoint = self::BASE_URL . $endpoint;
if ($method === 'GET') {
return $this->getInstance()->getClient()?->request(
method: $method,
endpoint: $endpoint,
query_string: $queryString
);
} else {
return $this->getInstance()->getClient()->request($method, $endpoint, [
'json' => ($payload),
]);
}
}
/**
* @throws BadRequest
* @throws HubspotException
*/
public function createMeeting(array $payload): Response
{
$endpoint = '/crm/v3/objects/meetings';
return $this->makeRequest($endpoint, 'POST', $payload);
}
/**
* @throws BadRequest
* @throws HubspotException
*/
public function updateMeeting(string $meetingId, array $payload): Response
{
$endpoint = '/crm/v3/objects/meetings/' . $meetingId;
return $this->makeRequest($endpoint, 'PATCH', $payload);
}
/**
* @throws \Exception
*/
public function createNote(
string $body,
string $ownerId,
int $timestamp,
string $objectId,
NoteObject $noteObject
): ?string {
try {
$noteInput = new SimplePublicObjectInput([
'properties' => [
'hs_note_body' => $body,
'hubspot_owner_id' => $ownerId,
'hs_timestamp' => $timestamp,
],
]);
// Create note
$note = $this->getNewInstance()->crm()->objects()->basicApi()->create('note', $noteInput);
$this->getNewInstance()->crm()->objects()->associationsApi()->create(
'note',
$note->getId(),
$this->getNoteObject($noteObject),
$objectId,
$this->getNoteAssociationType($noteObject),
);
return $note->getId();
} catch (\Exception $e) {
$this->log->error('[Hubspot] Failed to create note', [
'objectId' => $objectId,
'noteObject' => $noteObject->getObjectType(),
'reason' => $e->getMessage(),
]);
\Sentry::captureException($e);
}
return null;
}
public function updateEngagement(string $objectId, array $engagement, array $metadata): void
{
$this->getInstance()->engagements()->update($objectId, $engagement, $metadata);
}
public function getEngagementData(string $engagementId): array
{
$engagement = $this->getInstance()->engagements()->get($engagementId);
return $engagement->toArray();
}
public function createEngagement(array $engagement, array $associations, array $metadata): Response
{
return $this->getInstance()
->engagements()
->create($engagement, $associations, $metadata);
}
public function isUnauthorizedException(\Exception $e): bool
{
// Check for specific HubSpot API exception types first
if ($e instanceof BadRequest) {
// BadRequest can contain 401 status codes
return $e->getCode() === 401;
}
// Check for HTTP client exceptions with status codes
if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
$response = $e->getResponse();
if ($response !== null) {
return $response->getStatusCode() === 401;
}
}
// Check for Guzzle HTTP exceptions
if ($e instanceof \GuzzleHttp\Exception\ClientException) {
return $e->getCode() === 401;
}
// Fallback to string matching as last resort, but be more specific
$message = strtolower($e->getMessage());
return str_contains($message, '401 unauthorized') ||
str_contains($message, 'http 401') ||
str_contains($message, 'status code 401') ||
(preg_match('/\b401\b/', $message) && str_contains($message, 'unauthorized'));
}
/**
* Validates and refreshes the access token if needed before API requests.
* This ensures long-running processes don't fail due to token expiration.
*
* @throws SocialAccountTokenInvalidException
*/
public function ensureValidToken(): void
{
if ($this->oauthAccount === null) {
return;
}
$newToken = $this->tokenManager->ensureValidToken($this->oauthAccount);
if ($newToken !== null) {
$this->accessToken = $newToken;
}
}
public function getConfig()
{
return $this->config;
}
// returns only active (archived=false)
public function getOwners(): array
{
return $this->getNewInstance()->crm()->owners()->getAll();
}
/**
* @param bool $archived
*
* @return array<Owner>|[]
*/
public function getOwnersArchived(bool $archived = true): array
{
$endpoint = '/crm/v3/owners';
$queryParams = [
'archived' => $archived ? 'true' : 'false',
];
$queryString = http_build_query($queryParams);
$owners = [];
try {
$response = $this->makeRequest(endpoint: $endpoint, queryString: $queryString);
$responseData = $response?->toArray();
foreach ($responseData['results'] as $result) {
try {
$owners[] = Owner::create($result);
} catch (Throwable $e) {
$this->log->error('[HubSpot] Failed to process owner data', [
'result' => $result,
'error' => $e->getMessage(),
]);
continue;
}
}
} catch (Throwable $e) {
$this->log->error('HubSpot] Failed to fetch owners', [
'archived' => $archived,
'error' => $e->getMessage(),
]);
return [];
}
return $owners;
}
public function getMeeting(string $engagementId): ObjectWithAssociations
{
return $this->getNewInstance()->crm()->objects()->basicApi()
->getById('meeting', $engagementId, null, 'contact,company,deal');
}
public function deleteEngagement(string $engagementId): void
{
$this->getInstance()->engagements()->delete((int) $engagementId);
}
public function getAssociationsData(array $ids, string $fromObject, string $toObject): array
{
$associationData = [];
$idChunks = array_chunk($ids, self::ASSOCIATIONS_BATCH_SIZE_LIMIT);
foreach ($idChunks as $idChunk) {
try {
$batchInput = new \HubSpot\Client\Crm\Associations\Model\BatchInputPublicObjectId();
$batchInput->setInputs(array_map(function ($id) {
$publicObjectId = new \HubSpot\Client\Crm\Associations\Model\PublicObjectId();
$publicObjectId->setId($id);
return $publicObjectId;
}, $idChunk));
$associatedObjectsData = $this
->getNewInstance()
->crm()
->associations()
->batchApi()
->read($fromObject, $toObject, $batchInput);
if ($associatedObjectsData instanceof \HubSpot\Client\Crm\Associations\Model\BatchResponsePublicAssociationMulti) {
foreach ($associatedObjectsData->getResults() as $association) {
$from = $association->getFrom()->getId();
$toAssociations = $association->getTo();
if (! empty($toAssociations)) {
$associationData[$from] = array_map(function ($item) {
return $item->getId();
}, $toAssociations);
}
}
}
} catch (\Exception $e) {
$this->log->error('[Hubspot] Failed to fetch associations', [
'from_object' => $fromObject,
'to_object' => $toObject,
'reason' => $e->getMessage(),
]);
}
}
return $associationData;
}
/**
* @throws \Exception
*/
private function getNoteAssociationType(NoteObject $noteObject): string
{
return match($noteObject) {
NoteObject::Opportunity => 'note_to_deal',
NoteObject::Lead, NoteObject::Contact => 'note_to_contact', // or 'note_to_lead' if your portal supports it
NoteObject::Account => 'note_to_company',
NoteObject::Call, NoteObject::Event => throw new \Exception('Not supported'),
};
}
/**
* @throws \Exception
*/
private function getNoteObject(NoteObject $noteObject): string
{
return match($noteObject) {
NoteObject::Opportunity => 'deal',
NoteObject::Lead, NoteObject::Contact => 'contact',
NoteObject::Account => 'company',
NoteObject::Call, NoteObject::Event => throw new \Exception('Not supported'),
};
}
public function addAssociations(string $objectType, string $associationType, array $payload): Response
{
$endpoint = "/crm/v4/associations/$objectType/$associationType/batch/create";
return $this->makeRequest($endpoint, 'POST', $payload);
}
public function removeAssociations(string $objectType, string $associationType, array $payload): Response
{
$endpoint = "/crm/v4/associations/$objectType/$associationType/batch/archive";
return $this->makeRequest($endpoint, 'POST', $payload);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85248
|
2921
|
3
|
2026-05-28T12:14:24.869300+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970464869_m2.jpg...
|
PhpStorm
|
faVsco.js – Client.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
SIUCKWindowHelpPwovscors#12121 on JY-20963-folProi SIUCKWindowHelpPwovscors#12121 on JY-20963-folProinet vecanyice pn.he bolbees.phe©ActivityControlier.php© VoiceConsentPrefix.phpNotificationsnObservers© AccountObserver.phpCyActwwooserver.pnp© ContactObserver.phgGroupObserver.pho© LeadObserver.phoC ProfileObserver.phpC SocialAccountObserver.phg© UserObserver.pho© UserRoleObserver.pho(in Policie:aProviders• Queuea Reoositonea RulesaServicesDa ActivityAiReodrleallendarConnerimermobiacte@ DecorateActivityDummym Helnarsv D Hubspol(i) AccountSyncStrategyMAetioneMcontndSuncstrateon• D DTO› FieldsThtauendOLeAkоkyscrco.onC Teamuprp183Opportunivsvncstratcov- Pac nation- Prosoec-SearchStrateo→- RedisService traits• Utils- Wechookc) Batchsunceorector cho© BatchSvncRedsService.oCleantonoCLeAAA Den CTadAcCenoeclnaalise rccarica onoOneindi.onoC) Client.php X php autoload.phdMWiaKorCass wochexebaseuoehraocathies wueswethheat* Breturn T The result of the APi callprivate function executeRequest(callable SapiCall)ScacheKey = Sthis->getRateLimitCacheKeyOScacheocxozresac = keozst.oet scachekeyif (is_string(ScachedExpiresAt) && is_numeric(ScachedExpiresAt)) 1Sremaining = naxl vax(cint)) ScachedExpiresAt - tineon:hrow new kaceLinzcexceoe.onsrenaining,reruonSant waittercarch ethronadteoi4 (Sthiso>isHubsootRateLinit(Se))thisosparse?erny.er e// NX: only the first job to receive a 429 in this burst sets the key.// Subsequent 42%s in the same burst leave the TTL untouched so theIl window is not reset by every concurrent job hitting the linit.Redis::set(ScacheKey, (string) (tine() + SretryAfter).options:'EX', SretryAfter, "NX*);app/Services/Crm/Hubspot/Client.php:183Sthis->log->warning( Hubspot) Received 429 from API'.iteanSdl"conffa Kd= Sthis->config->getido."retry after'as Scetryatter=> Se->getMessageOthrow new RateLinitException message: "Hubspot returned 429'. SretryAfter. Se):Throw Senprivate function getRateLinitCachekevO: strinol...;=custom.loglaravel.logA console [STAGING-782785704785786711[712713[PHONE]725727728729E732-733—730737- 738)TX: AUTONAND a.created_at › DATE_:GROUP BY u.id, u.email,ORDER BY sns_count DESCselect + Eron teans, wherlselect + Eron coles,CEIEOTCONCATU.Id, CASE WHsa.*t.ouner id FROM sociJOIN users u on u.id = sJOIN teans tWHERE u.tean_id = 1117 aSELECT * FROM actávitioSELECT * FROM actávitioSELECT * FROM crn configSELECT # FROM teans WHERselleetron usens whenselect * fron playbooksseleetron miawhonkeselect * fron playbook_ctseleet ron eoeselect * fron crn_field.vSELECT * FROM crn_field_AOTM con Brelds 4 0M 4• JOIN activities a ON $NHERF Actvity "d = 7002AND € con onovider saSELECT * FROM activity.mselect * fron text relayselect * fron activitiesselect * fron users whenPARAtT GAAR MANGUREANOPAlRetGhAn dAAAIRdAMselect & fron teans wherPhat"toon actytysHoeDMsActivityMonJiminnY ….# backend# buescontusion-dinig# donut_time#enpineerine# general# happy birthdavA infocoe intemal all# infra-chansed# infrastructure de#bu-team-infoiliminnv-bo# platform-team# platform-ticketstoroduct launche# random# release# suppor# thank-youssie the neoole of fimill6? Direct message.Vasil VasilenF8. Stefka Stoyanova1a llivana NetsevaA Ctovan TomnulPetko KashinskiGola Nimitrous: Todor Stamator1 Stelivan Georsie.&r MireNikolav Vanko&. James GrahamLukas Kovalky7o0sLXInu cowoy 1o:14.2-@ Describe what you are looking forVasil Vasileve MessagerNoR0d canvis7 Files+Vasil Vasilev 2:56 PM1 с добър коментарDoory2e intentionaЗ сьщо e intentional поради факта, че phpredis dniver-a не поддьржа set ex +nх параметри, и тряова да се пуснат две операции set + expireLukas Kovalik 3.07 PMок. зз по пуснах пак поез gеminіlза третата точка обаче наистина ли няма подьржкааз май си ги ползвам някьлеVasil Vasilev 3:10 PMне става, бях го направил така, и се счупиLukas Kovalik 3:10 PMами и при мен се чумешеVasil Vasilev 3:11 PMpredis поддьржа set(Skey. Svalue. nx' - true, ex =60)Cnhnranic He caRaLukas Kovalik 3.14pNтака май не работеше Sresult = Redis=set(Stestkey, StestValue, "ax, Sttl, "NX*); а така да Sresult = Redis:set(StestKey, StestValue, [nx, 'ex' => Sttl)):Vasil Vasiley 2.11 pwLukas Kovalik 3.12 pNне помно BеUEVasil Vasilev 3:12 PMobоитноtо може nаeLukas Kovalik 3-12 PMможе и ла брькамVacil Vaciley 242 pwewons uusSlockAcquired - Redis::set(self::POLLING LOCK KEY, ison encode(SlockData). "EX', self::LOCK TTL SECONDS. *NX*))значи пьрвото работиLukas Kovalik 313 PMwe to ononns...
|
NULL
|
1963937319043274319
|
NULL
|
click
|
ocr
|
NULL
|
SIUCKWindowHelpPwovscors#12121 on JY-20963-folProi SIUCKWindowHelpPwovscors#12121 on JY-20963-folProinet vecanyice pn.he bolbees.phe©ActivityControlier.php© VoiceConsentPrefix.phpNotificationsnObservers© AccountObserver.phpCyActwwooserver.pnp© ContactObserver.phgGroupObserver.pho© LeadObserver.phoC ProfileObserver.phpC SocialAccountObserver.phg© UserObserver.pho© UserRoleObserver.pho(in Policie:aProviders• Queuea Reoositonea RulesaServicesDa ActivityAiReodrleallendarConnerimermobiacte@ DecorateActivityDummym Helnarsv D Hubspol(i) AccountSyncStrategyMAetioneMcontndSuncstrateon• D DTO› FieldsThtauendOLeAkоkyscrco.onC Teamuprp183Opportunivsvncstratcov- Pac nation- Prosoec-SearchStrateo→- RedisService traits• Utils- Wechookc) Batchsunceorector cho© BatchSvncRedsService.oCleantonoCLeAAA Den CTadAcCenoeclnaalise rccarica onoOneindi.onoC) Client.php X php autoload.phdMWiaKorCass wochexebaseuoehraocathies wueswethheat* Breturn T The result of the APi callprivate function executeRequest(callable SapiCall)ScacheKey = Sthis->getRateLimitCacheKeyOScacheocxozresac = keozst.oet scachekeyif (is_string(ScachedExpiresAt) && is_numeric(ScachedExpiresAt)) 1Sremaining = naxl vax(cint)) ScachedExpiresAt - tineon:hrow new kaceLinzcexceoe.onsrenaining,reruonSant waittercarch ethronadteoi4 (Sthiso>isHubsootRateLinit(Se))thisosparse?erny.er e// NX: only the first job to receive a 429 in this burst sets the key.// Subsequent 42%s in the same burst leave the TTL untouched so theIl window is not reset by every concurrent job hitting the linit.Redis::set(ScacheKey, (string) (tine() + SretryAfter).options:'EX', SretryAfter, "NX*);app/Services/Crm/Hubspot/Client.php:183Sthis->log->warning( Hubspot) Received 429 from API'.iteanSdl"conffa Kd= Sthis->config->getido."retry after'as Scetryatter=> Se->getMessageOthrow new RateLinitException message: "Hubspot returned 429'. SretryAfter. Se):Throw Senprivate function getRateLinitCachekevO: strinol...;=custom.loglaravel.logA console [STAGING-782785704785786711[712713[PHONE]725727728729E732-733—730737- 738)TX: AUTONAND a.created_at › DATE_:GROUP BY u.id, u.email,ORDER BY sns_count DESCselect + Eron teans, wherlselect + Eron coles,CEIEOTCONCATU.Id, CASE WHsa.*t.ouner id FROM sociJOIN users u on u.id = sJOIN teans tWHERE u.tean_id = 1117 aSELECT * FROM actávitioSELECT * FROM actávitioSELECT * FROM crn configSELECT # FROM teans WHERselleetron usens whenselect * fron playbooksseleetron miawhonkeselect * fron playbook_ctseleet ron eoeselect * fron crn_field.vSELECT * FROM crn_field_AOTM con Brelds 4 0M 4• JOIN activities a ON $NHERF Actvity "d = 7002AND € con onovider saSELECT * FROM activity.mselect * fron text relayselect * fron activitiesselect * fron users whenPARAtT GAAR MANGUREANOPAlRetGhAn dAAAIRdAMselect & fron teans wherPhat"toon actytysHoeDMsActivityMonJiminnY ….# backend# buescontusion-dinig# donut_time#enpineerine# general# happy birthdavA infocoe intemal all# infra-chansed# infrastructure de#bu-team-infoiliminnv-bo# platform-team# platform-ticketstoroduct launche# random# release# suppor# thank-youssie the neoole of fimill6? Direct message.Vasil VasilenF8. Stefka Stoyanova1a llivana NetsevaA Ctovan TomnulPetko KashinskiGola Nimitrous: Todor Stamator1 Stelivan Georsie.&r MireNikolav Vanko&. James GrahamLukas Kovalky7o0sLXInu cowoy 1o:14.2-@ Describe what you are looking forVasil Vasileve MessagerNoR0d canvis7 Files+Vasil Vasilev 2:56 PM1 с добър коментарDoory2e intentionaЗ сьщо e intentional поради факта, че phpredis dniver-a не поддьржа set ex +nх параметри, и тряова да се пуснат две операции set + expireLukas Kovalik 3.07 PMок. зз по пуснах пак поез gеminіlза третата точка обаче наистина ли няма подьржкааз май си ги ползвам някьлеVasil Vasilev 3:10 PMне става, бях го направил така, и се счупиLukas Kovalik 3:10 PMами и при мен се чумешеVasil Vasilev 3:11 PMpredis поддьржа set(Skey. Svalue. nx' - true, ex =60)Cnhnranic He caRaLukas Kovalik 3.14pNтака май не работеше Sresult = Redis=set(Stestkey, StestValue, "ax, Sttl, "NX*); а така да Sresult = Redis:set(StestKey, StestValue, [nx, 'ex' => Sttl)):Vasil Vasiley 2.11 pwLukas Kovalik 3.12 pNне помно BеUEVasil Vasilev 3:12 PMobоитноtо може nаeLukas Kovalik 3-12 PMможе и ла брькамVacil Vaciley 242 pwewons uusSlockAcquired - Redis::set(self::POLLING LOCK KEY, ison encode(SlockData). "EX', self::LOCK TTL SECONDS. *NX*))значи пьрвото работиLukas Kovalik 313 PMwe to ononns...
|
85246
|
NULL
|
NULL
|
NULL
|
|
85247
|
2920
|
3
|
2026-05-28T12:14:24.758208+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970464758_m1.jpg...
|
PhpStorm
|
faVsco.js – Client.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
PhpStormFileEditViewNavigateCodeRefactorRunToolsGi PhpStormFileEditViewNavigateCodeRefactorRunToolsGitWindowHelpec2-user@ip-10-30-129-190:~screenpipe"O ₴4‹$0(ah]A100% <478• Thu 28 May 15:14:24181ec2-user@ip-10-30-140-…₴7DOCKER#_####_#####\\###||\#/V~'881DEV (-zsh)O [EMAIL] Linux 2023 (ECS Optimized)_/m/For documentation, visit [URL_WITH_CREDENTIALS] ~]$ exitlogoutConnection to jiminny-prod-ecsi closed.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ applukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ vprodWarning: Permanently added 'jiminny-prod-ecs1' (ED25519) to the list of known hosts.A newer release of "Amazon Linux" is available.Version 2023.10.20260330:Version 2023.11.20260406:Version 2023.11.20260413:Version2023.11.20260427:Version2023.11.20260505:Version 2023.11.20260509:Version 2023.11.20260511:Version 2023.11.20260514:Run "/usr/bin/dnf check-release-update" for full release and version update info#_~\ ####_\ #####\\###1\#/Amazon Linux 2023 (ECS Optimized)/m/'For documentation, visit [URL_WITH_CREDENTIALS] ~]$ client_loop: send disconnect: Broken pipeukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-relay) $I...
|
NULL
|
5311969006285717777
|
NULL
|
click
|
ocr
|
NULL
|
PhpStormFileEditViewNavigateCodeRefactorRunToolsGi PhpStormFileEditViewNavigateCodeRefactorRunToolsGitWindowHelpec2-user@ip-10-30-129-190:~screenpipe"O ₴4‹$0(ah]A100% <478• Thu 28 May 15:14:24181ec2-user@ip-10-30-140-…₴7DOCKER#_####_#####\\###||\#/V~'881DEV (-zsh)O [EMAIL] Linux 2023 (ECS Optimized)_/m/For documentation, visit [URL_WITH_CREDENTIALS] ~]$ exitlogoutConnection to jiminny-prod-ecsi closed.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ applukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ vprodWarning: Permanently added 'jiminny-prod-ecs1' (ED25519) to the list of known hosts.A newer release of "Amazon Linux" is available.Version 2023.10.20260330:Version 2023.11.20260406:Version 2023.11.20260413:Version2023.11.20260427:Version2023.11.20260505:Version 2023.11.20260509:Version 2023.11.20260511:Version 2023.11.20260514:Run "/usr/bin/dnf check-release-update" for full release and version update info#_~\ ####_\ #####\\###1\#/Amazon Linux 2023 (ECS Optimized)/m/'For documentation, visit [URL_WITH_CREDENTIALS] ~]$ client_loop: send disconnect: Broken pipeukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-relay) $I...
|
85245
|
NULL
|
NULL
|
NULL
|
|
85246
|
2921
|
2
|
2026-05-28T12:14:08.791289+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970448791_m2.jpg...
|
Slack
|
Vasil Vasilev (DM) - Jiminny Inc - 2 new items - S Vasil Vasilev (DM) - Jiminny Inc - 2 new items - Slack...
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Vasil Vasilev
Today at 12:00:25 PM
12:00 PM
Здрасти, Лукаш
Today at 12:00:27 PM
12:00
готов си
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки
Today at 1:25:47 PM
1:25
процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип
Today at 1:26:15 PM
1:26
и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity
Lukas Kovalik
Today at 2:45:12 PM
2:45 PM
Не знам това дали е релевантно
Today at 2:45:14 PM
2:45
1.
Shared Elasticsearch Sockets:
Because
pcntl_fork()
clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in
resetAfterFork()
(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and
cURL
exceptions.
2.
Supervisor Shutdown Deadlock:
In
reapChildren()
, calling
pcntl_waitpid()
without the
WNOHANG
flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.
(edited)
Today at 2:45:29 PM
2:45
3.
Non-Atomic Redis Locks:
The new
ReindexTargetStatsReporter
checks the lock with
get
and then creates it with
set
. Because the workers are truly parallel, they can both read
null
at the exact same microsecond and both push duplicate metrics to Datadog. This needs to be a single, atomic command (e.g.,
set
with
NX
).
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions
Vasil Vasilev
Today at 2:56:52 PM
2:56 PM
1 e добър коментар,
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions
Today at 2:56:55 PM
2:56...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"bounds":{"left":0.5056516,"top":0.058260176,"width":0.011968086,"height":0.028731046},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"bounds":{"left":0.50299203,"top":0.10055866,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"bounds":{"left":0.50664896,"top":0.13806863,"width":0.009973404,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"bounds":{"left":0.50299203,"top":0.15482841,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":8,"bounds":{"left":0.50764626,"top":0.19233839,"width":0.007978723,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":6,"bounds":{"left":0.50299203,"top":0.20909816,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":8,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.012965426,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.0026595744,"height":0.011173184}},{"char_start":1,"char_count":7,"bounds":{"left":0.50764626,"top":0.24660814,"width":0.010638298,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":6,"bounds":{"left":0.50299203,"top":0.26336792,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":8,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0076462766,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5099734,"top":0.3008779,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Later","depth":6,"bounds":{"left":0.50299203,"top":0.31763768,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Later","depth":8,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.008643617,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5093085,"top":0.35514766,"width":0.0066489363,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"More…","depth":6,"bounds":{"left":0.50299203,"top":0.3719074,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"More","depth":8,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.008976064,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.0033244682,"height":0.011173184}},{"char_start":1,"char_count":3,"bounds":{"left":0.5106383,"top":0.4094174,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXStaticText","text":"Unreads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Threads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Huddles","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Drafts & sent","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Directories","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-backend-engineers","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-inner-team","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ai-chapter","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"alerts","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"backend","depth":15,"bounds":{"left":0.5422208,"top":0.09736632,"width":0.018284574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.09736632,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54521275,"top":0.09736632,"width":0.015292553,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"bugs","depth":15,"bounds":{"left":0.5422208,"top":0.11971269,"width":0.010638298,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.11971269,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":3,"bounds":{"left":0.54521275,"top":0.11971269,"width":0.00731383,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"confusion-clinic","depth":15,"bounds":{"left":0.5422208,"top":0.14205906,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.14205906,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54454786,"top":0.14205906,"width":0.032247342,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"donut_time","depth":15,"bounds":{"left":0.5422208,"top":0.16440542,"width":0.025265958,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.16440542,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54521275,"top":0.16440542,"width":0.022273935,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"engineering","depth":15,"bounds":{"left":0.5422208,"top":0.1867518,"width":0.025930852,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.1867518,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":10,"bounds":{"left":0.54488033,"top":0.1867518,"width":0.022938829,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"general","depth":15,"bounds":{"left":0.5422208,"top":0.20909816,"width":0.016289894,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.20909816,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54488033,"top":0.20909816,"width":0.013297873,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"happy_birthday","depth":15,"bounds":{"left":0.5422208,"top":0.23144454,"width":0.033909574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.23144454,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.54521275,"top":0.23144454,"width":0.030917553,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infosec_internal_all","depth":15,"bounds":{"left":0.5422208,"top":0.25379092,"width":0.041888297,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.25379092,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":19,"bounds":{"left":0.54355055,"top":0.25379092,"width":0.040226065,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infra-changes","depth":15,"bounds":{"left":0.5422208,"top":0.27613726,"width":0.029587766,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.27613726,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54355055,"top":0.27613726,"width":0.02825798,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infrastructure_dev","depth":15,"bounds":{"left":0.5422208,"top":0.29848364,"width":0.040226065,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.29848364,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":17,"bounds":{"left":0.54355055,"top":0.29848364,"width":0.038896278,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"jbu-team-info","depth":15,"bounds":{"left":0.5422208,"top":0.32083002,"width":0.029920213,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.32083002,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54355055,"top":0.32083002,"width":0.028590426,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"jiminny-bg","depth":15,"bounds":{"left":0.5422208,"top":0.34317636,"width":0.023271276,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.34317636,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54355055,"top":0.34317636,"width":0.021609042,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"platform-team","depth":15,"bounds":{"left":0.5422208,"top":0.36552274,"width":0.03158245,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.36552274,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54521275,"top":0.36552274,"width":0.028590426,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"platform-tickets","depth":15,"bounds":{"left":0.5422208,"top":0.38786912,"width":0.034906916,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.38786912,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54521275,"top":0.38786912,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"product_launches","depth":15,"bounds":{"left":0.5422208,"top":0.4102155,"width":0.03856383,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.4102155,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54521275,"top":0.4102155,"width":0.03557181,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"random","depth":15,"bounds":{"left":0.5422208,"top":0.43256184,"width":0.016954787,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.43256184,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":5,"bounds":{"left":0.54421544,"top":0.43256184,"width":0.014960106,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"releases","depth":15,"bounds":{"left":0.5422208,"top":0.45490822,"width":0.018284574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.45490822,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":7,"bounds":{"left":0.54421544,"top":0.45490822,"width":0.016289894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"support","depth":15,"bounds":{"left":0.5422208,"top":0.4772546,"width":0.017287234,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.4772546,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54454786,"top":0.4772546,"width":0.01462766,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"thank-yous","depth":15,"bounds":{"left":0.5422208,"top":0.49960095,"width":0.024601065,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.49960095,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54421544,"top":0.49960095,"width":0.022606382,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"the_people_of_jiminny","depth":15,"bounds":{"left":0.5422208,"top":0.5219473,"width":0.045212764,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5219473,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":20,"bounds":{"left":0.54421544,"top":0.5219473,"width":0.04720745,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Vasil Vasilev","depth":15,"bounds":{"left":0.5422208,"top":0.5746209,"width":0.026595745,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5746209,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54521275,"top":0.5746209,"width":0.023271276,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Stefka Stoyanova","depth":15,"bounds":{"left":0.5422208,"top":0.5969673,"width":0.037898935,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5969673,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54488033,"top":0.5969673,"width":0.03523936,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Iliyana Netseva","depth":15,"bounds":{"left":0.5422208,"top":0.61931366,"width":0.03324468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.61931366,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54355055,"top":0.61931366,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Stoyan Tomov","depth":15,"bounds":{"left":0.5422208,"top":0.64166003,"width":0.030917553,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.64166003,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":11,"bounds":{"left":0.54488033,"top":0.64166003,"width":0.027925532,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Petko Kashinski","depth":15,"bounds":{"left":0.5422208,"top":0.6640064,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.6640064,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54521275,"top":0.6640064,"width":0.03158245,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Galya Dimitrova","depth":15,"bounds":{"left":0.5422208,"top":0.6863527,"width":0.03523936,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.6863527,"width":0.003656915,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54587764,"top":0.6863527,"width":0.03158245,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Todor Stamatov","depth":15,"bounds":{"left":0.5422208,"top":0.7086991,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7086991,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.54454786,"top":0.7086991,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Steliyan Georgiev","depth":15,"bounds":{"left":0.5422208,"top":0.7310455,"width":0.038231384,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7310455,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":16,"bounds":{"left":0.54488033,"top":0.7310455,"width":0.03557181,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Ves","depth":15,"bounds":{"left":0.5422208,"top":0.75339186,"width":0.007978723,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.75339186,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":2,"bounds":{"left":0.54521275,"top":0.75339186,"width":0.004986702,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Mira","depth":15,"bounds":{"left":0.5422208,"top":0.77573824,"width":0.010305851,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.77573824,"width":0.004654255,"height":0.014365523}},{"char_start":1,"char_count":3,"bounds":{"left":0.546875,"top":0.77573824,"width":0.005319149,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Nikolay Yankov","depth":15,"bounds":{"left":0.5422208,"top":0.7980846,"width":0.032912236,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7980846,"width":0.0039893617,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.5462101,"top":0.7980846,"width":0.028922873,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"James Graham","depth":15,"bounds":{"left":0.5422208,"top":0.820431,"width":0.031914894,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.820431,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":11,"bounds":{"left":0.54421544,"top":0.820431,"width":0.029920213,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Lukas Kovalik","depth":15,"bounds":{"left":0.5422208,"top":0.8427773,"width":0.029587766,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.8427773,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54488033,"top":0.8427773,"width":0.026928192,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"you","depth":15,"bounds":{"left":0.5744681,"top":0.8427773,"width":0.0063164895,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5744681,"top":0.8427773,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":2,"bounds":{"left":0.5767952,"top":0.8427773,"width":0.0056515955,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Jira Cloud","depth":15,"bounds":{"left":0.5422208,"top":0.8954509,"width":0.021941489,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.8954509,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54421544,"top":0.8954509,"width":0.019946808,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Toast","depth":15,"bounds":{"left":0.5422208,"top":0.91779727,"width":0.011635638,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.91779727,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":4,"bounds":{"left":0.54454786,"top":0.91779727,"width":0.00930851,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Google Calendar","depth":15,"bounds":{"left":0.5422208,"top":0.94014364,"width":0.030585106,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.94014364,"width":0.003656915,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54587764,"top":0.94014364,"width":0.032912236,"height":0.014365523}}],"role_description":"text"},{"role":"AXRadioButton","text":"Messages","depth":9,"bounds":{"left":0.60206115,"top":0.09177973,"width":0.030917553,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Messages","depth":11,"bounds":{"left":0.61136967,"top":0.10055866,"width":0.018949468,"height":0.012769354},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.61136967,"top":0.10055866,"width":0.0039893617,"height":0.012769354}},{"char_start":1,"char_count":7,"bounds":{"left":0.61535907,"top":0.10055866,"width":0.014960106,"height":0.012769354}}],"role_description":"text"},{"role":"AXRadioButton","text":"Add canvas","depth":10,"bounds":{"left":0.63397604,"top":0.09177973,"width":0.034242023,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Add canvas","depth":12,"bounds":{"left":0.64328456,"top":0.10055866,"width":0.022273935,"height":0.012769354},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.64328456,"top":0.10055866,"width":0.0033244682,"height":0.012769354}},{"char_start":1,"char_count":9,"bounds":{"left":0.6462766,"top":0.10055866,"width":0.019281914,"height":0.012769354}}],"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":9,"bounds":{"left":0.66921544,"top":0.09177973,"width":0.020944148,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":11,"bounds":{"left":0.67852396,"top":0.10055866,"width":0.008976064,"height":0.012769354},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Pins","depth":9,"bounds":{"left":0.69148934,"top":0.09177973,"width":0.020279255,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Pins","depth":11,"bounds":{"left":0.70079786,"top":0.10055866,"width":0.00831117,"height":0.012769354},"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Add and Edit Channel Tabs","depth":9,"bounds":{"left":0.71276593,"top":0.09177973,"width":0.010970744,"height":0.030327214},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Canvas","depth":9,"bounds":{"left":0.59640956,"top":0.0518755,"width":0.015957447,"height":0.0007980846},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"List","depth":9,"bounds":{"left":0.59640956,"top":0.0518755,"width":0.007978723,"height":0.0007980846},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Folder","depth":9,"bounds":{"left":0.59640956,"top":0.0518755,"width":0.013962766,"height":0.0007980846},"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Jump to date","depth":14,"bounds":{"left":0.7849069,"top":0.12689546,"width":0.025265958,"height":0.022346368},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:25 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Здрасти, Лукаш","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:27 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"готов си","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:37 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"малко по късно и на мен ще ми трябва ревю за един голям feature","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:46 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"но ще ти пиша, като е готов за гледане","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(edited)","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:11:37 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:11 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ок , mersi","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:23:53 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:23 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"като имаш време, разгледай този интересен ПР:","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"https://github.com/jiminny/app/pull/12130","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"https://github.com/jiminny/app/pull/12130","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:25:05 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:25","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:25:47 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:25","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:26:15 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:26","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:12 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Не знам това дали е релевантно","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:14 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1.","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Shared Elasticsearch Sockets:","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Because","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"pcntl_fork()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"resetAfterFork()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"cURL","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"exceptions.","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"2.","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Supervisor Shutdown Deadlock:","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"In","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"reapChildren()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":", calling","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"pcntl_waitpid()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"without the","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"WNOHANG","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.","depth":15,"bounds":{"left":0.6180186,"top":0.11572227,"width":0.3620346,"height":0.0071827616},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"","depth":15,"bounds":{"left":0.9212101,"top":0.11572227,"width":0.0013297872,"height":0.0071827616},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"(edited)","depth":15,"bounds":{"left":0.9225399,"top":0.11572227,"width":0.014295213,"height":0.0071827616},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"","depth":15,"bounds":{"left":0.93650264,"top":0.11572227,"width":0.0013297872,"height":0.0071827616},"on_screen":true,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:29 PM","depth":16,"bounds":{"left":0.60738033,"top":0.1348763,"width":0.007978723,"height":0.011173184},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45","depth":17,"bounds":{"left":0.60738033,"top":0.1348763,"width":0.007978723,"height":0.011173184},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"3.","depth":16,"bounds":{"left":0.6180186,"top":0.13248204,"width":0.0056515955,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Non-Atomic Redis Locks:","depth":16,"bounds":{"left":0.62333775,"top":0.13248204,"width":0.055518616,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"The new","depth":16,"bounds":{"left":0.6788564,"top":0.13248204,"width":0.021276595,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ReindexTargetStatsReporter","depth":17,"bounds":{"left":0.70146275,"top":0.1348763,"width":0.06216755,"height":0.011971269},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"checks the lock with","depth":16,"bounds":{"left":0.7649601,"top":0.13248204,"width":0.04720745,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"get","depth":17,"bounds":{"left":0.8131649,"top":0.1348763,"width":0.00731383,"height":0.011971269},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"and then creates it with","depth":16,"bounds":{"left":0.8218085,"top":0.13248204,"width":0.05418883,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"set","depth":17,"bounds":{"left":0.87699467,"top":0.1348763,"width":0.00731383,"height":0.011971269},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":". Because the workers are truly parallel, they can both read","depth":16,"bounds":{"left":0.6180186,"top":0.13248204,"width":0.37300533,"height":0.031923383},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"null","depth":17,"bounds":{"left":0.64162236,"top":0.15243416,"width":0.009640957,"height":0.011971269},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"at the exact same microsecond and both push duplicate metrics to Datadog. This needs to be a single, atomic command (e.g.,","depth":16,"bounds":{"left":0.6525931,"top":0.15003991,"width":0.27393618,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"set","depth":17,"bounds":{"left":0.9275266,"top":0.15243416,"width":0.00731383,"height":0.011971269},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"with","depth":16,"bounds":{"left":0.9361702,"top":0.15003991,"width":0.012300532,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"NX","depth":17,"bounds":{"left":0.9494681,"top":0.15243416,"width":0.004986702,"height":0.011971269},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":").","depth":16,"bounds":{"left":0.95578456,"top":0.15003991,"width":0.0026595744,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"React with white_check_mark","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with eyes","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with raised_hands","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Add reaction…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Reply in thread","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Forward message…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Save for later","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXPopUpButton","text":"More actions","depth":17,"on_screen":false,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"bounds":{"left":0.6180186,"top":0.17238627,"width":0.027593086,"height":0.017557861},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"bounds":{"left":0.6456117,"top":0.17398244,"width":0.0026595744,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXLink","text":"Today at 2:56:52 PM","depth":15,"bounds":{"left":0.64793885,"top":0.1763767,"width":0.015292553,"height":0.011173184},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:56 PM","depth":16,"bounds":{"left":0.64793885,"top":0.1763767,"width":0.015292553,"height":0.011173184},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1 e добър коментар,","depth":16,"bounds":{"left":0.6180186,"top":0.1915403,"width":0.04720745,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"React with white_check_mark","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with eyes","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with raised_hands","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Add reaction…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Reply in thread","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Forward message…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Save for later","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXPopUpButton","text":"More actions","depth":17,"on_screen":false,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Today at 2:56:55 PM","depth":16,"bounds":{"left":0.60738033,"top":0.21787709,"width":0.007978723,"height":0.011173184},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:56","depth":17,"bounds":{"left":0.60738033,"top":0.21787709,"width":0.007978723,"height":0.011173184},"on_screen":true,"role_description":"text"}]...
|
-444327709298478899
|
-2155617536517369762
|
click
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Vasil Vasilev
Today at 12:00:25 PM
12:00 PM
Здрасти, Лукаш
Today at 12:00:27 PM
12:00
готов си
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки
Today at 1:25:47 PM
1:25
процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип
Today at 1:26:15 PM
1:26
и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity
Lukas Kovalik
Today at 2:45:12 PM
2:45 PM
Не знам това дали е релевантно
Today at 2:45:14 PM
2:45
1.
Shared Elasticsearch Sockets:
Because
pcntl_fork()
clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in
resetAfterFork()
(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and
cURL
exceptions.
2.
Supervisor Shutdown Deadlock:
In
reapChildren()
, calling
pcntl_waitpid()
without the
WNOHANG
flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.
(edited)
Today at 2:45:29 PM
2:45
3.
Non-Atomic Redis Locks:
The new
ReindexTargetStatsReporter
checks the lock with
get
and then creates it with
set
. Because the workers are truly parallel, they can both read
null
at the exact same microsecond and both push duplicate metrics to Datadog. This needs to be a single, atomic command (e.g.,
set
with
NX
).
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions
Vasil Vasilev
Today at 2:56:52 PM
2:56 PM
1 e добър коментар,
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions
Today at 2:56:55 PM
2:56
SIUCKWindowHelpPwovscors#12121 on JY-20963-folProinet vecanyice pn.he bolbees.phe©ActivityControlier.php© VoiceConsentPrefix.phpNotificationsnObservers© AccountObserver.phpCyActwwooserver.pnp© ContactObserver.phgGroupObserver.pho© LeadObserver.phoC ProfileObserver.phpC SocialAccountObserver.phg© UserObserver.pho© UserRoleObserver.pho(in Policie:aProviders• Queuea Reoositonea RulesaServicesDa ActivityAiReodrleallendarConnerimermobiacte@ DecorateActivityDummym Helnarsv D Hubspol(i) AccountSyncStrategyMAetioneMcontndSuncstrateon• D DTO› FieldsThtauendOLeAkоkyscrco.onC Teamuprp183Opportunivsvncstratcov- Pac nation- Prosoec-SearchStrateo→- RedisService traits• Utils- Wechookc) Batchsunceorector cho© BatchSvncRedisService.oCleantonoCLeAAA Den CTadAcCenoeclnaalise rccarica onoOneindi.onoC) Client.php X php autoload.phdMWiaKorCass wochexebaseuoehraocathies wueswethheat* Breturn T The result of the APi callprivate function executeRequest(callable SapiCall)ScacheKey = Sthis->getRateLimitCacheKeyOScacheocxozresac = keozst.oet scachekeyif (is_string(ScachedExpiresAt) && is_numeric(ScachedExpiresAt)) 1Sremaining = naxl vax(cint)) ScachedExpiresAt - tineon:hrow new kacetinzcexceoezonsrenaining,reruonSant waittercarch leinronabieoi4 (Sthiso>isHubsootRateLinit(Se))thisosparse?erry.er e// NX: only the first job to receive a 429 in this burst sets the key.// Subsequent 42%s in the same burst leave the TTL untouched so theIl window is not reset by every concurrent job hitting the linit.Redis::set(ScacheKey, (string) (tine() + SretryAfter).options:'EX', SretryAfter, "NX*);app/Services/Crm/Hubspot/Client.php:183Sthis->log->warning( Hubspot) Received 429 from API'. (iteanSdl"conffa Kd= Sthis->config->getido."retry after'as Scetryatter=> Se->getMessageOthrow new RateLinitException message: "Hubspot returned 429'. SretryAfter. Se):Throw Senprivate function getRateLinitCachekevO: strinol...;=custom.loglaravel.logA console (STAGING)-782785704705785789—718711[712713714-215-717HIUBE!722725727728729- 77—73073- 738)TX: AUTONAND a.created_at › DATE_:GROUP BY u.id, u.email,ORDER BY sns_count DESC;select + Eron teans, wherlselect + Eron coles,SELECTCONCATU.Id, CASE WHsa.*t.ouner id FROM sociJOIN users u on u.id = sJOIN teans tWHERE u.tean_id = 1117 aSELECT * FROM activitioSELECT * FROM actávitioSELECT * FROM crn configSELECT * FROM teans WHERHselleetron usens whenselect + fron olavbookselect * fron playbook_ctseleet ron eoeselect * fron crn_field.vSELECT * FROM crn_field_AOTM con Brelds 4 0M 4• JOIN activities a ON $WHERE activity_id = 7993AAND € eon onoviden salSELECT * FROM activity.mselect * fron text relayselect * fron activitiesselect * fron users whenPARAtT GAAR MANGUREANOPAlRetGhAn dAAAIRdAMHoeDMsAhiwitJiminnY ….# backend# buescontusion-dinig# donut_time#enpineerine# general# hapoy birthdavA infocoe intemal all# infra-chansed# infrastructure de#bu-team-infoiliminnv-bost olatform-team# platform-ticketstoroduct launche# random# release# suppor# thank-youssie the neoole of fimill6? Direct message.Vasil VasilenF8. Stefka Stoyanova1a llivana NetsevaA Ctovan TomnulPetko Kashinski( Galva Dimitrova P: Todor Stamatol1 Stelivan Georsie.D Vod&r MireNikolav Vanko&. James GrahamLukas Kovalky#:Appsai Gooele CalelInu cowoy 10:14.0e@ Describe what you are looking forVasil VasilevAdd canvasfiles.3. Non-Atomic Redis Locks: The new ReindexTargetStatsReporter checksti loday i get and then creates it with set. Because the workers are truly parallel, they canboth read null at the exact same microsecond and both push duplicate metrics to Datados. This needs to be a single, atomic command (c.s.. set with NX),Vasil Vasilev 2:56 PM1 е добър коментарe intenhona*сьшlo e intentonal порали оакта, че ohoredis слvеr-а не подльожа sет ех +их парзметои, и тояова ля се пуснат лве опеозции set + exoireLukas Kovalik 3.07 psOKerko nverwuhiknoee cenntthва тостата точка обаче наистина ли няма полтоожкааз май си ги ползвам някьлоили е друг driverVasil Vasilev 3:10 PMне става, бях го направил така, и се счупьlmkas Kovalllk 2atd omами и при мен се чумешеVasil Vasilev 3:11 PMpredis поддьржа set(Skey, Svalue. nx' = true, ex =60)c ohoredis не cтaтLukas Kovalik 3411 pkтака майіме оавотане, лосине насежантоиксув иотуамоахо иикмхекашака лав тосине колсисьь поiкоув суamо dinкeсy2 SillVasil Vasiley 3-11 pyLukas Kovalik 3:12 pNне помня вечеVasil Vasilev 3.12 PMобратното може ла сlukae Kovalik 242 omможе и да брькамNacll Nachlou 2novoMOnsuNsSlockAcquired - Redis::set(self::POLLING LOCK KEY, ison encode(SlockData). *EX', self::LOCK TTL SECONDS. "NX")ZHRUM NILARATO MANATLLukas Kovalik 3:13 PMna u sano/Services/Grm/Hubsnot/Glient.oho:102Message Vasil Vasile...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85245
|
2920
|
2
|
2026-05-28T12:14:08.688077+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970448688_m1.jpg...
|
Slack
|
Vasil Vasilev (DM) - Jiminny Inc - 2 new items - S Vasil Vasilev (DM) - Jiminny Inc - 2 new items - Slack...
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Vasil Vasilev
Today at 12:00:25 PM
12:00 PM
Здрасти, Лукаш
Today at 12:00:27 PM
12:00
готов си
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки
Today at 1:25:47 PM
1:25
процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип
Today at 1:26:15 PM
1:26
и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity
Lukas Kovalik
Today at 2:45:12 PM
2:45 PM
Не знам това дали е релевантно
Today at 2:45:14 PM
2:45
1.
Shared Elasticsearch Sockets:
Because
pcntl_fork()...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Later","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Later","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"More…","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"More","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Unreads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Threads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Huddles","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Drafts & sent","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Directories","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-backend-engineers","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-inner-team","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ai-chapter","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"alerts","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"backend","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"bugs","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"confusion-clinic","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"donut_time","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"engineering","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"general","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"happy_birthday","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infosec_internal_all","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infra-changes","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infrastructure_dev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"jbu-team-info","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"jiminny-bg","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"platform-team","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"platform-tickets","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"product_launches","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"random","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"releases","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"support","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"thank-yous","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"the_people_of_jiminny","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Vasil Vasilev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Stefka Stoyanova","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Iliyana Netseva","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Stoyan Tomov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Petko Kashinski","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Galya Dimitrova","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Todor Stamatov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Steliyan Georgiev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Ves","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Mira","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Nikolay Yankov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"James Graham","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Lukas Kovalik","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"you","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Jira Cloud","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Toast","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Google Calendar","depth":15,"bounds":{"left":0.56805557,"top":0.0,"width":0.06388889,"height":0.02},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.56805557,"top":0.0,"width":0.007638889,"height":0.02}},{"char_start":1,"char_count":14,"bounds":{"left":0.57569444,"top":0.0,"width":0.06875,"height":0.02}}],"role_description":"text"},{"role":"AXRadioButton","text":"Messages","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Messages","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Add canvas","depth":10,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Add canvas","depth":12,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Pins","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Pins","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Add and Edit Channel Tabs","depth":9,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Canvas","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"List","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Folder","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Jump to date","depth":14,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:25 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Здрасти, Лукаш","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:27 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"готов си","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:37 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"малко по късно и на мен ще ми трябва ревю за един голям feature","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:46 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"но ще ти пиша, като е готов за гледане","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(edited)","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:11:37 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:11 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ок , mersi","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:23:53 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:23 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"като имаш време, разгледай този интересен ПР:","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"https://github.com/jiminny/app/pull/12130","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"https://github.com/jiminny/app/pull/12130","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:25:05 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:25","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:25:47 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:25","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:26:15 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:26","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:12 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Не знам това дали е релевантно","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:14 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1.","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Shared Elasticsearch Sockets:","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Because","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"pcntl_fork()","depth":16,"on_screen":false,"role_description":"text"}]...
|
-3754903620119380753
|
222263413097863034
|
click
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Vasil Vasilev
Today at 12:00:25 PM
12:00 PM
Здрасти, Лукаш
Today at 12:00:27 PM
12:00
готов си
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки
Today at 1:25:47 PM
1:25
процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип
Today at 1:26:15 PM
1:26
и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity
Lukas Kovalik
Today at 2:45:12 PM
2:45 PM
Не знам това дали е релевантно
Today at 2:45:14 PM
2:45
1.
Shared Elasticsearch Sockets:
Because
pcntl_fork()
PhpStormFileEditViewNavigateCodeRefactorRunToolsGitWindowHelpec2-user@ip-10-30-129-190:~screenpipe"O ₴4‹$0(ah]A100% <78• Thu 28 May 15:14:08181ec2-user@ip-10-30-140-...₴7DOCKER#_####_#####\\###||\#/V~'881DEV (-zsh)O [EMAIL] Linux 2023 (ECS Optimized)_/m/For documentation, visit [URL_WITH_CREDENTIALS] ~]$ exitlogoutConnection to jiminny-prod-ecsi closed.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ applukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ vprodWarning: Permanently added 'jiminny-prod-ecs1' (ED25519) to the list of known hosts.A newer release of "Amazon Linux" is available.Version 2023.10.20260330:Version 2023.11.20260406:Version 2023.11.20260413:Version2023.11.20260427:Version2023.11.20260505:Version 2023.11.20260509:Version 2023.11.20260511:Version 2023.11.20260514:Run "/usr/bin/dnf check-release-update" for full release and version update info#_~\ ####_\ #####\\###1\#/Amazon Linux 2023 (ECS Optimized)/m/'For documentation, visit [URL_WITH_CREDENTIALS] ~]$ client_loop: send disconnect: Broken pipeukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-relay) $I...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85244
|
2920
|
1
|
2026-05-28T12:13:55.933019+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970435933_m1.jpg...
|
Slack
|
Vasil Vasilev (DM) - Jiminny Inc - 2 new items - S Vasil Vasilev (DM) - Jiminny Inc - 2 new items - Slack...
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Vasil Vasilev
Today at 12:00:25 PM
12:00 PM
Здрасти, Лукаш
Today at 12:00:27 PM
12:00
готов си
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки
Today at 1:25:47 PM
1:25
процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип
Today at 1:26:15 PM
1:26
и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity
Lukas Kovalik
Today at 2:45:12 PM
2:45 PM
Не знам това дали е релевантно
Today at 2:45:14 PM
2:45
1.
Shared Elasticsearch Sockets:
Because
pcntl_fork()
clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in
resetAfterFork()
(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and
cURL
exceptions.
2.
Supervisor Shutdown Deadlock:
In
reapChildren()
, calling
pcntl_waitpid()
without the
WNOHANG
flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.
(edited)
Today at 2:45:29 PM...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Later","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Later","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"More…","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"More","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Unreads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Threads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Huddles","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Drafts & sent","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Directories","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-backend-engineers","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-inner-team","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ai-chapter","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"alerts","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"backend","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"bugs","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"confusion-clinic","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"donut_time","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"engineering","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"general","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"happy_birthday","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infosec_internal_all","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infra-changes","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infrastructure_dev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"jbu-team-info","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"jiminny-bg","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"platform-team","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"platform-tickets","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"product_launches","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"random","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"releases","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"support","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"thank-yous","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"the_people_of_jiminny","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Vasil Vasilev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Stefka Stoyanova","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Iliyana Netseva","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Stoyan Tomov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Petko Kashinski","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Galya Dimitrova","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Todor Stamatov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Steliyan Georgiev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Ves","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Mira","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Nikolay Yankov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"James Graham","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Lukas Kovalik","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"you","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Jira Cloud","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Toast","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Google Calendar","depth":15,"bounds":{"left":0.56805557,"top":0.0,"width":0.06388889,"height":0.02},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.56805557,"top":0.0,"width":0.007638889,"height":0.02}},{"char_start":1,"char_count":14,"bounds":{"left":0.57569444,"top":0.0,"width":0.06875,"height":0.02}}],"role_description":"text"},{"role":"AXRadioButton","text":"Messages","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Messages","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Add canvas","depth":10,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Add canvas","depth":12,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Pins","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Pins","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Add and Edit Channel Tabs","depth":9,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Canvas","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"List","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Folder","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Jump to date","depth":15,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Vasil Vasilev","depth":16,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:25 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00 PM","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Здрасти, Лукаш","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:27 PM","depth":17,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":18,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"готов си","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:37 PM","depth":17,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":18,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"малко по късно и на мен ще ми трябва ревю за един голям feature","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:46 PM","depth":17,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":18,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"но ще ти пиша, като е готов за гледане","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(edited)","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":16,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:11:37 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:11 PM","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ок , mersi","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Vasil Vasilev","depth":16,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:23:53 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:23 PM","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"като имаш време, разгледай този интересен ПР:","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"https://github.com/jiminny/app/pull/12130","depth":17,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"https://github.com/jiminny/app/pull/12130","depth":18,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:25:05 PM","depth":17,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:25","depth":18,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:25:47 PM","depth":17,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:25","depth":18,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:26:15 PM","depth":17,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:26","depth":18,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":16,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:12 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45 PM","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Не знам това дали е релевантно","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:14 PM","depth":17,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45","depth":18,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1.","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Shared Elasticsearch Sockets:","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Because","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"pcntl_fork()","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"resetAfterFork()","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"cURL","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"exceptions.","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"2.","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Supervisor Shutdown Deadlock:","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"In","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"reapChildren()","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":", calling","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"pcntl_waitpid()","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"without the","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"WNOHANG","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"(edited)","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:29 PM","depth":17,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
5510432311640652852
|
222267879729894014
|
typing_pause
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Vasil Vasilev
Today at 12:00:25 PM
12:00 PM
Здрасти, Лукаш
Today at 12:00:27 PM
12:00
готов си
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки
Today at 1:25:47 PM
1:25
процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип
Today at 1:26:15 PM
1:26
и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity
Lukas Kovalik
Today at 2:45:12 PM
2:45 PM
Не знам това дали е релевантно
Today at 2:45:14 PM
2:45
1.
Shared Elasticsearch Sockets:
Because
pcntl_fork()
clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in
resetAfterFork()
(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and
cURL
exceptions.
2.
Supervisor Shutdown Deadlock:
In
reapChildren()
, calling
pcntl_waitpid()
without the
WNOHANG
flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.
(edited)
Today at 2:45:29 PM
PhpStormFileEditViewNavigateCodeRefactorRunToolsGitWindowHelpec2-user@ip-10-30-129-190:~screenpipe"O ₴4‹$0(ah]A100% <78• Thu 28 May 15:13:55181ec2-user@ip-10-30-140-…₴7DOCKER#_####_#####\\###||\#/V~'881DEV (-zsh)O [EMAIL] Linux 2023 (ECS Optimized)_/m/For documentation, visit [URL_WITH_CREDENTIALS] ~]$ exitlogoutConnection to jiminny-prod-ecsi closed.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ applukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ vprodWarning: Permanently added 'jiminny-prod-ecs1' (ED25519) to the list of known hosts.A newer release of "Amazon Linux" is available.Version 2023.10.20260330:Version 2023.11.20260406:Version 2023.11.20260413:Version2023.11.20260427:Version2023.11.20260505:Version 2023.11.20260509:Version 2023.11.20260511:Version 2023.11.20260514:Run "/usr/bin/dnf check-release-update" for full release and version update info#_~\ ####_\ #####\\###1\#/Amazon Linux 2023 (ECS Optimized)/m/'For documentation, visit [URL_WITH_CREDENTIALS] ~]$ client_loop: send disconnect: Broken pipeukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-relay) $I...
|
85242
|
NULL
|
NULL
|
NULL
|
|
85243
|
2921
|
1
|
2026-05-28T12:13:54.891119+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970434891_m2.jpg...
|
Slack
|
Vasil Vasilev (DM) - Jiminny Inc - 2 new items - S Vasil Vasilev (DM) - Jiminny Inc - 2 new items - Slack...
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"bounds":{"left":0.5056516,"top":0.058260176,"width":0.011968086,"height":0.028731046},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"bounds":{"left":0.50299203,"top":0.10055866,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"bounds":{"left":0.50664896,"top":0.13806863,"width":0.009973404,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"bounds":{"left":0.50299203,"top":0.15482841,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":8,"bounds":{"left":0.50764626,"top":0.19233839,"width":0.007978723,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":6,"bounds":{"left":0.50299203,"top":0.20909816,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":8,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.012965426,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.0026595744,"height":0.011173184}},{"char_start":1,"char_count":7,"bounds":{"left":0.50764626,"top":0.24660814,"width":0.010638298,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":6,"bounds":{"left":0.50299203,"top":0.26336792,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":8,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0076462766,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5099734,"top":0.3008779,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Later","depth":6,"bounds":{"left":0.50299203,"top":0.31763768,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Later","depth":8,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.008643617,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5093085,"top":0.35514766,"width":0.0066489363,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"More…","depth":6,"bounds":{"left":0.50299203,"top":0.3719074,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"More","depth":8,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.008976064,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.0033244682,"height":0.011173184}},{"char_start":1,"char_count":3,"bounds":{"left":0.5106383,"top":0.4094174,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXStaticText","text":"Unreads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Threads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Huddles","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Drafts & sent","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Directories","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-backend-engineers","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-inner-team","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ai-chapter","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"alerts","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"backend","depth":15,"bounds":{"left":0.5422208,"top":0.09736632,"width":0.018284574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.09736632,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54521275,"top":0.09736632,"width":0.015292553,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"bugs","depth":15,"bounds":{"left":0.5422208,"top":0.11971269,"width":0.010638298,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.11971269,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":3,"bounds":{"left":0.54521275,"top":0.11971269,"width":0.00731383,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"confusion-clinic","depth":15,"bounds":{"left":0.5422208,"top":0.14205906,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.14205906,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54454786,"top":0.14205906,"width":0.032247342,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"donut_time","depth":15,"bounds":{"left":0.5422208,"top":0.16440542,"width":0.025265958,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.16440542,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54521275,"top":0.16440542,"width":0.022273935,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"engineering","depth":15,"bounds":{"left":0.5422208,"top":0.1867518,"width":0.025930852,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.1867518,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":10,"bounds":{"left":0.54488033,"top":0.1867518,"width":0.022938829,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"general","depth":15,"bounds":{"left":0.5422208,"top":0.20909816,"width":0.016289894,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.20909816,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54488033,"top":0.20909816,"width":0.013297873,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"happy_birthday","depth":15,"bounds":{"left":0.5422208,"top":0.23144454,"width":0.033909574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.23144454,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.54521275,"top":0.23144454,"width":0.030917553,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infosec_internal_all","depth":15,"bounds":{"left":0.5422208,"top":0.25379092,"width":0.041888297,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.25379092,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":19,"bounds":{"left":0.54355055,"top":0.25379092,"width":0.040226065,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infra-changes","depth":15,"bounds":{"left":0.5422208,"top":0.27613726,"width":0.029587766,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.27613726,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54355055,"top":0.27613726,"width":0.02825798,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infrastructure_dev","depth":15,"bounds":{"left":0.5422208,"top":0.29848364,"width":0.040226065,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.29848364,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":17,"bounds":{"left":0.54355055,"top":0.29848364,"width":0.038896278,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"jbu-team-info","depth":15,"bounds":{"left":0.5422208,"top":0.32083002,"width":0.029920213,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.32083002,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54355055,"top":0.32083002,"width":0.028590426,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"jiminny-bg","depth":15,"bounds":{"left":0.5422208,"top":0.34317636,"width":0.023271276,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.34317636,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54355055,"top":0.34317636,"width":0.021609042,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"platform-team","depth":15,"bounds":{"left":0.5422208,"top":0.36552274,"width":0.03158245,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.36552274,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54521275,"top":0.36552274,"width":0.028590426,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"platform-tickets","depth":15,"bounds":{"left":0.5422208,"top":0.38786912,"width":0.034906916,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.38786912,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54521275,"top":0.38786912,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"product_launches","depth":15,"bounds":{"left":0.5422208,"top":0.4102155,"width":0.03856383,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.4102155,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54521275,"top":0.4102155,"width":0.03557181,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"random","depth":15,"bounds":{"left":0.5422208,"top":0.43256184,"width":0.016954787,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.43256184,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":5,"bounds":{"left":0.54421544,"top":0.43256184,"width":0.014960106,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"releases","depth":15,"bounds":{"left":0.5422208,"top":0.45490822,"width":0.01761968,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.45490822,"width":0.0016622341,"height":0.014365523}},{"char_start":1,"char_count":7,"bounds":{"left":0.54388297,"top":0.45490822,"width":0.015957447,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"support","depth":15,"bounds":{"left":0.5422208,"top":0.4772546,"width":0.017287234,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.4772546,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54454786,"top":0.4772546,"width":0.01462766,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"thank-yous","depth":15,"bounds":{"left":0.5422208,"top":0.49960095,"width":0.024601065,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.49960095,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54421544,"top":0.49960095,"width":0.022606382,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"the_people_of_jiminny","depth":15,"bounds":{"left":0.5422208,"top":0.5219473,"width":0.045212764,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5219473,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":20,"bounds":{"left":0.54421544,"top":0.5219473,"width":0.04720745,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Vasil Vasilev","depth":15,"bounds":{"left":0.5422208,"top":0.5746209,"width":0.026595745,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5746209,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54521275,"top":0.5746209,"width":0.023271276,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Stefka Stoyanova","depth":15,"bounds":{"left":0.5422208,"top":0.5969673,"width":0.037898935,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5969673,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54488033,"top":0.5969673,"width":0.03523936,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Iliyana Netseva","depth":15,"bounds":{"left":0.5422208,"top":0.61931366,"width":0.03324468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.61931366,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54355055,"top":0.61931366,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Stoyan Tomov","depth":15,"bounds":{"left":0.5422208,"top":0.64166003,"width":0.030917553,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.64166003,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":11,"bounds":{"left":0.54488033,"top":0.64166003,"width":0.027925532,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Petko Kashinski","depth":15,"bounds":{"left":0.5422208,"top":0.6640064,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.6640064,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54521275,"top":0.6640064,"width":0.03158245,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Galya Dimitrova","depth":15,"bounds":{"left":0.5422208,"top":0.6863527,"width":0.03523936,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.6863527,"width":0.003656915,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54587764,"top":0.6863527,"width":0.03158245,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Todor Stamatov","depth":15,"bounds":{"left":0.5422208,"top":0.7086991,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7086991,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.54454786,"top":0.7086991,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Steliyan Georgiev","depth":15,"bounds":{"left":0.5422208,"top":0.7310455,"width":0.038231384,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7310455,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":16,"bounds":{"left":0.54488033,"top":0.7310455,"width":0.03557181,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Ves","depth":15,"bounds":{"left":0.5422208,"top":0.75339186,"width":0.007978723,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.75339186,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":2,"bounds":{"left":0.54521275,"top":0.75339186,"width":0.004986702,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Mira","depth":15,"bounds":{"left":0.5422208,"top":0.77573824,"width":0.010305851,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.77573824,"width":0.004654255,"height":0.014365523}},{"char_start":1,"char_count":3,"bounds":{"left":0.546875,"top":0.77573824,"width":0.005319149,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Nikolay Yankov","depth":15,"bounds":{"left":0.5422208,"top":0.7980846,"width":0.032912236,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7980846,"width":0.0039893617,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.5462101,"top":0.7980846,"width":0.028922873,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"James Graham","depth":15,"bounds":{"left":0.5422208,"top":0.820431,"width":0.031914894,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.820431,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":11,"bounds":{"left":0.54421544,"top":0.820431,"width":0.029920213,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Lukas Kovalik","depth":15,"bounds":{"left":0.5422208,"top":0.8427773,"width":0.029587766,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.8427773,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54488033,"top":0.8427773,"width":0.026928192,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"you","depth":15,"bounds":{"left":0.5744681,"top":0.8427773,"width":0.0063164895,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5744681,"top":0.8427773,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":2,"bounds":{"left":0.5767952,"top":0.8427773,"width":0.0056515955,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Jira Cloud","depth":15,"bounds":{"left":0.5422208,"top":0.8954509,"width":0.021941489,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.8954509,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54421544,"top":0.8954509,"width":0.019946808,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Toast","depth":15,"bounds":{"left":0.5422208,"top":0.91779727,"width":0.011635638,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.91779727,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":4,"bounds":{"left":0.54454786,"top":0.91779727,"width":0.00930851,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Google Calendar","depth":15,"bounds":{"left":0.5422208,"top":0.94014364,"width":0.030585106,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.94014364,"width":0.003656915,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54587764,"top":0.94014364,"width":0.032912236,"height":0.014365523}}],"role_description":"text"},{"role":"AXRadioButton","text":"Messages","depth":9,"bounds":{"left":0.60206115,"top":0.09177973,"width":0.030917553,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Messages","depth":11,"bounds":{"left":0.61136967,"top":0.10055866,"width":0.018949468,"height":0.012769354},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.61136967,"top":0.10055866,"width":0.0039893617,"height":0.012769354}},{"char_start":1,"char_count":7,"bounds":{"left":0.61535907,"top":0.10055866,"width":0.014960106,"height":0.012769354}}],"role_description":"text"}]...
|
2472280325389673958
|
-5802369499738826006
|
visual_change
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
SIUCKWindowHelpPwovscors#12121 on JY-20963-folProinet vecanyice pn.he bolbees.phe©ActivityControlier.php© VoiceConsentPrefix.phpNotificationsnObservers© AccountObserver.phpCyActwwooserver.pnp© ContactObserver.phpGroupObserver.pho© LeadObserver.phoC ProfileObserver.phpC SocialAccountObserver.phg© UserObserver.pho© UserRoleObserver.phc(in Policie:aProviders• Queuea Reoositonea RulesaServicesActivityAiReodrleallendarConnerimermobiacte@ DecorateActivityDummym Helnarsv D Hubspol(i) AccountSyncStrategyMAetioneMcontndSuncstrateon• D DTO› FieldsThtauendOLeAkоkyscrco.onC Teamuprp183Opportunivsvncstratcov- Pac nation- Prosoec-SearchStrateo→- RedisService traits• Utils- Wechookc) Batchsunceorector cho© BatchSvncRedisService.oCleantonoCLeAAA Den CTadAcCenoeclnaalise rccarica onoOneindi.onoC) Client.php X php autoload.phdMWiaKorCass wochexebaseuoehraocathies wueswethheat* Breturn T The result of the APi callprivate function executeRequest(callable SapiCall)ScacheKey = Sthis->getRateLimitCacheKeyOScacheotxozresac = keozst.oet scachekey)*if (is_string(ScachedExpiresAt) && is_numeric(ScachedExpiresAt)) 1Sremaining = naxl vax(cint)) ScachedExpiresAt - tineon:hrow new kacetinzcexceoezonsrenaining,neruonSantwaittecarch ethronadteoi4 (Sthiso>isHubsootRateLinit(Se))thisosparse?erry.er e// NX: only the first job to receive a 429 in this burst sets the key./l Subsequent 429s in the same burst leave the TTL untouched so theIl window is not reset by every concurrent job hitting the linit.Redis::set(ScacheKey, (string) (tine() + SretryAfter).options:'EX', SretryAfter, "NX*);app/Services/Crm/Hubspot/Client.php:183Sthis->log->warning( Hubspot) Received 429 from API'.iteanSdl"conffa Kd= Sthis->config->getido."retry after'as Scetryatter-ENAeMAONNATthrow new RateLinitException message: "Hubspot returned 429'. SretryAfter. Se):Throw Senprivate function getRateLinitCachekevO: strinol...;=custom.loglaravel.logA console (STAGING)-782783704705785707=718711713[PHONE]22725727728729—730- 738)—749TX: AUTONAND a.created_at › DATE_:GROUP BY u.id, u.email,ORDER BY sns_count DESC;select + Eron teans, wherlselect + Eron coles,SELECTCONCATU.Id, CASE WHsa.*t.ouner id FROM sociJOIN users u on u.id = sJOIN teans tWHERE u.tean_id = 1117 aSELECT * FROM activitioSELECT * FROM actávitioSELECT * FROM crn configSELECT * FROM teans WHERHselleetron usens whenselect + fron olavbookselect * fron playbook_ctseleet ron eoeselect * fron crn_field.vSELECT * FROM crn_field_AOTM con Brelds 4 0M 4• JOIN activities a ON $6WHERE activity_id = 7993AND € con onovider saSELECT * FROM activity.mselect * fron text relayselect * fron activitiesselect * fron users whenPARAtT GAAR MANGUREANOPAlRetGhAn dAAAIRdAMselect * fron teans wherHoeDM:Arhivht• Thu 28 May 15:13:54JiminnY ….# backend# buescontusion-dinig#donut time#enpineerine# general# happy birthdavA infocoe intemal all# infra-chansed# infrastructure de#bu-team-infoiliminnv-bost olatform-team# platform-ticketstoroduct launche# random# released# suppor# thank-youssie the neoole of fimill6? Direct message.F8. Stefka Stoyanova1a llivana Netsevachuan omauPetko KashinskiGola Nimitrous: Todor Stamator1 Stelivan Georsie.&r MireNikolav Vanko&. James GrahamLukas Kovalky#:AppsS lin Gloud@ Describe what you are looking forVasil VasilevAdd canvas7 File2. Supervisor Shutdown Deadlock: In reapChildren®, callins pontl_waitpiilooayt the WNOHANG flag makes it a blockine call. If one child process gets stuck (c.g.waiting on a network timeout), the parent supervisor will freeze indehnitely and completely ignore your 10-second graceful shutdown lozic. (edited)3. Non-Atomic Redis Locks: The new ReindexTargetStatsReporter checks the lock with get and then creates it with set . Because the workers are truly parallel, they carboth read null at the exact same microsecond and both push duplicate metrics to Datados. This needs to be a sinale, atomic command (e.?. set with NX)).Vasil Vasilev 2:56 PM1 е добър коментарe intentonaККСНО ФлеелкОлИЕКОФИИИ ОИІКЕЛКУС ОНОК-ФТЬКОТУ-ЕЛТЬе ВОТАБОЖЕ БУЙ ССОХСТАХ ГОНОЯ МОНОМНИ ТОДОВИ АЙТСЯТЛУСЬНІ СЛЕ-ОЛФОНИМИКЯ СЕОХОЛЕLukas Kovalik 3.07 PMаз май си ги ползвам някьдеили е друг driverVasil Vasilev 3:10 PMне става бех го наплавил така и се симоиtkac Kowaiik 2utniomами и при мен се чумешеVasil Vasilev 3:11 PMoredrs nonnsowa setSkow Svalue.lIinx = tmie. ex =c.0lConnrodis he craReLukas Kovalik 3:11 pNтака май не работеше Sresult = Redis-set(StestKey, StestValue, 'SX. StI. "NX"): а така ла Sresult = Rediswset(StestKey, StestValue. l'nx' 'ex' => Stll):Vasil Vasiley 3411 PvLukas Kovalik 3:12 PMне помня вечіVasil Vasilev 3:12 PMобратното може да сtkse Kowsll4 242.o1/може и да бръкамVacl Vacllev 2.12 pvRkOna uMаSlockAcquired - Redis::set(self::POLLING_LOCK_KEY, ison_encode(SlockData), "EX', self::LOCK_TTL_SECONDS, *NX")значи пьовото работила и в app/Services/Crm//Hubspot/Client pho:103...
|
85241
|
NULL
|
NULL
|
NULL
|
|
85242
|
2920
|
0
|
2026-05-28T12:13:49.396281+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970429396_m1.jpg...
|
Slack
|
Vasil Vasilev (DM) - Jiminny Inc - 2 new items - S Vasil Vasilev (DM) - Jiminny Inc - 2 new items - Slack...
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Lukas Kovalik
Today at 11:55:58 AM
11:55 AM
здрасти Васко, може ли един approve
https://github.com/jiminny/app/pull/12136
https://github.com/jiminny/app/pull/12136
Vasil Vasilev
Today at 12:00:25 PM
12:00 PM
Здрасти, Лукаш
Today at 12:00:27 PM
12:00
готов си
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Later","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Later","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"More…","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"More","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Unreads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Threads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Huddles","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Drafts & sent","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Directories","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-backend-engineers","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-inner-team","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ai-chapter","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"alerts","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"backend","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"bugs","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"confusion-clinic","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"donut_time","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"engineering","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"general","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"happy_birthday","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infosec_internal_all","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infra-changes","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infrastructure_dev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"jbu-team-info","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"jiminny-bg","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"platform-team","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"platform-tickets","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"product_launches","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"random","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"releases","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"support","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"thank-yous","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"the_people_of_jiminny","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Vasil Vasilev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Stefka Stoyanova","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Iliyana Netseva","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Stoyan Tomov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Petko Kashinski","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Galya Dimitrova","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Todor Stamatov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Steliyan Georgiev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Ves","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Mira","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Nikolay Yankov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"James Graham","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Lukas Kovalik","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"you","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Jira Cloud","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Toast","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Google Calendar","depth":15,"bounds":{"left":0.56805557,"top":0.0,"width":0.06388889,"height":0.02},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.56805557,"top":0.0,"width":0.007638889,"height":0.02}},{"char_start":1,"char_count":14,"bounds":{"left":0.57569444,"top":0.0,"width":0.06875,"height":0.02}}],"role_description":"text"},{"role":"AXRadioButton","text":"Messages","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Messages","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Add canvas","depth":10,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Add canvas","depth":12,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Pins","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Pins","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Add and Edit Channel Tabs","depth":9,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Canvas","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"List","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Folder","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Jump to date","depth":14,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 11:55:58 AM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"11:55 AM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"здрасти Васко, може ли един approve","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"https://github.com/jiminny/app/pull/12136","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"https://github.com/jiminny/app/pull/12136","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:25 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Здрасти, Лукаш","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:27 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"готов си","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:37 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"малко по късно и на мен ще ми трябва ревю за един голям feature","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:46 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"но ще ти пиша, като е готов за гледане","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(edited)","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:11:37 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:11 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ок , mersi","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:23:53 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:23 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"като имаш време, разгледай този интересен ПР:","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"https://github.com/jiminny/app/pull/12130","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"https://github.com/jiminny/app/pull/12130","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:25:05 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:25","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки","depth":16,"on_screen":false,"role_description":"text"}]...
|
193665262607049812
|
-9001952430211885202
|
visual_change
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Lukas Kovalik
Today at 11:55:58 AM
11:55 AM
здрасти Васко, може ли един approve
https://github.com/jiminny/app/pull/12136
https://github.com/jiminny/app/pull/12136
Vasil Vasilev
Today at 12:00:25 PM
12:00 PM
Здрасти, Лукаш
Today at 12:00:27 PM
12:00
готов си
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки
PhpStormFileEditViewNavigateCodeRefactorRunToolsGitWindowHelpec2-user@ip-10-30-129-190:~screenpipe"84‹$0(ah]A100% <78 • Thu 28 May 15:13:49181ec2-user@ip-10-30-140-...₴7DOCKER#_####_#####\\###||\#/V~'881DEV (-zsh)O [EMAIL] Linux 2023 (ECS Optimized)_/m/For documentation, visit [URL_WITH_CREDENTIALS] ~]$ exitlogoutConnection to jiminny-prod-ecsi closed.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ applukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ vprodWarning: Permanently added 'jiminny-prod-ecs1' (ED25519) to the list of known hosts.A newer release of "Amazon Linux" is available.Version 2023.10.20260330:Version 2023.11.20260406:Version 2023.11.20260413:Version2023.11.20260427:Version2023.11.20260505:Version 2023.11.20260509:Version 2023.11.20260511:Version 2023.11.20260514:Run "/usr/bin/dnf check-release-update" for full release and version update info#_~\ ####_\ #####\\###1\#/Amazon Linux 2023 (ECS Optimized)/m/'For documentation, visit [URL_WITH_CREDENTIALS] ~]$ client_loop: send disconnect: Broken pipeukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-relay) $I...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85241
|
2921
|
0
|
2026-05-28T12:13:48.895681+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970428895_m2.jpg...
|
Slack
|
Vasil Vasilev (DM) - Jiminny Inc - 2 new items - S Vasil Vasilev (DM) - Jiminny Inc - 2 new items - Slack...
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"bounds":{"left":0.5056516,"top":0.058260176,"width":0.011968086,"height":0.028731046},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"bounds":{"left":0.50299203,"top":0.10055866,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"bounds":{"left":0.50664896,"top":0.13806863,"width":0.009973404,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"bounds":{"left":0.50299203,"top":0.15482841,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":8,"bounds":{"left":0.50764626,"top":0.19233839,"width":0.007978723,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":6,"bounds":{"left":0.50299203,"top":0.20909816,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":8,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.012965426,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.0026595744,"height":0.011173184}},{"char_start":1,"char_count":7,"bounds":{"left":0.50764626,"top":0.24660814,"width":0.010638298,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":6,"bounds":{"left":0.50299203,"top":0.26336792,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":8,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0076462766,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5099734,"top":0.3008779,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Later","depth":6,"bounds":{"left":0.50299203,"top":0.31763768,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Later","depth":8,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.008643617,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5093085,"top":0.35514766,"width":0.0066489363,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"More…","depth":6,"bounds":{"left":0.50299203,"top":0.3719074,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"More","depth":8,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.008976064,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.0033244682,"height":0.011173184}},{"char_start":1,"char_count":3,"bounds":{"left":0.5106383,"top":0.4094174,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXStaticText","text":"Unreads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Threads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Huddles","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Drafts & sent","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Directories","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-backend-engineers","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-inner-team","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ai-chapter","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"alerts","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"backend","depth":15,"bounds":{"left":0.5422208,"top":0.09736632,"width":0.018284574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.09736632,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54521275,"top":0.09736632,"width":0.015292553,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"bugs","depth":15,"bounds":{"left":0.5422208,"top":0.11971269,"width":0.010638298,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.11971269,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":3,"bounds":{"left":0.54521275,"top":0.11971269,"width":0.00731383,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"confusion-clinic","depth":15,"bounds":{"left":0.5422208,"top":0.14205906,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.14205906,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54454786,"top":0.14205906,"width":0.032247342,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"donut_time","depth":15,"bounds":{"left":0.5422208,"top":0.16440542,"width":0.025265958,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.16440542,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54521275,"top":0.16440542,"width":0.022273935,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"engineering","depth":15,"bounds":{"left":0.5422208,"top":0.1867518,"width":0.025930852,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.1867518,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":10,"bounds":{"left":0.54488033,"top":0.1867518,"width":0.022938829,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"general","depth":15,"bounds":{"left":0.5422208,"top":0.20909816,"width":0.016289894,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.20909816,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54488033,"top":0.20909816,"width":0.013297873,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"happy_birthday","depth":15,"bounds":{"left":0.5422208,"top":0.23144454,"width":0.033909574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.23144454,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.54521275,"top":0.23144454,"width":0.030917553,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infosec_internal_all","depth":15,"bounds":{"left":0.5422208,"top":0.25379092,"width":0.041888297,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.25379092,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":19,"bounds":{"left":0.54355055,"top":0.25379092,"width":0.040226065,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infra-changes","depth":15,"bounds":{"left":0.5422208,"top":0.27613726,"width":0.029587766,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.27613726,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54355055,"top":0.27613726,"width":0.02825798,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infrastructure_dev","depth":15,"bounds":{"left":0.5422208,"top":0.29848364,"width":0.040226065,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.29848364,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":17,"bounds":{"left":0.54355055,"top":0.29848364,"width":0.038896278,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"jbu-team-info","depth":15,"bounds":{"left":0.5422208,"top":0.32083002,"width":0.029920213,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.32083002,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54355055,"top":0.32083002,"width":0.028590426,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"jiminny-bg","depth":15,"bounds":{"left":0.5422208,"top":0.34317636,"width":0.023271276,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.34317636,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54355055,"top":0.34317636,"width":0.021609042,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"platform-team","depth":15,"bounds":{"left":0.5422208,"top":0.36552274,"width":0.03158245,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.36552274,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54521275,"top":0.36552274,"width":0.028590426,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"platform-tickets","depth":15,"bounds":{"left":0.5422208,"top":0.38786912,"width":0.034906916,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.38786912,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54521275,"top":0.38786912,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"product_launches","depth":15,"bounds":{"left":0.5422208,"top":0.4102155,"width":0.03856383,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.4102155,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54521275,"top":0.4102155,"width":0.03557181,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"random","depth":15,"bounds":{"left":0.5422208,"top":0.43256184,"width":0.016954787,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.43256184,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":5,"bounds":{"left":0.54421544,"top":0.43256184,"width":0.014960106,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"releases","depth":15,"bounds":{"left":0.5422208,"top":0.45490822,"width":0.01761968,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.45490822,"width":0.0016622341,"height":0.014365523}},{"char_start":1,"char_count":7,"bounds":{"left":0.54388297,"top":0.45490822,"width":0.015957447,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"support","depth":15,"bounds":{"left":0.5422208,"top":0.4772546,"width":0.017287234,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.4772546,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54454786,"top":0.4772546,"width":0.01462766,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"thank-yous","depth":15,"bounds":{"left":0.5422208,"top":0.49960095,"width":0.024601065,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.49960095,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54421544,"top":0.49960095,"width":0.022606382,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"the_people_of_jiminny","depth":15,"bounds":{"left":0.5422208,"top":0.5219473,"width":0.045212764,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5219473,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":20,"bounds":{"left":0.54421544,"top":0.5219473,"width":0.04720745,"height":0.014365523}}],"role_description":"text"}]...
|
-2514829430078690937
|
-5801313908410827038
|
visual_change
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
rapstomViewCoocWindowFV faVsco.s ~#12121 on JY-20963-fx-lproidetwnapers.oh© VoiceConsentPrefix.phpOLekоkyseiwico.onNotificationsv Observers© AccountObserver.phpMWiaKorC ActivityObserver.pho© ContactObserver.phpGroupObserver.pho© LeadObserver.phoC ProfileObserver.phpR82C SocialAccountObserver.phg© UserObserver.pho© UserRoleObserver.phc(in Policie:uProvider• Queuea Reoositonea RulesaServicesDa ActivityAiReodrleallendarConnerimermobiacte@ DecorateActivityDummym Helnarsv D Hubspol(i) AccountSyncStrategyIhctiontMcontctSwnestrateon• D DTO› FieldsThtauend183Opportunivsvncstratcov- Pac nation-ProsoecSearchStratco→- RedisService traits• # Utils- Wechookc) Batchsunceo ector cho© BatchSvncRedisService.oCleantonoCLeAAA Den CTadAcCenoeclnaalise rccarica ono© Kernel.phgCass wochexebaseuoehraocathies wueswethheat* Breturn T The result of the APi callprivate function executeRequest(callable SapiCall)ScacheKey = Sthis->getRateLimitCacheKeyOScacheotxozresac = keozst.oet scachekey)*if (is_string(ScachedExpiresAt) && is_numeric(ScachedExpiresAt)) 1Sremaining = naxl vax(cint)) ScachedExpiresAt - tineon:hrow new kaceLinzcexceoe.onsrenaining,neruonSantwaittecarch leinronabieoi4 (Sthiso>isHubsootRateLinit(Se))thisosparse?erny.er e// NX: only the first job to receive a 429 in this burst sets the key.// Subsequent 42%s in the same burst leave the TTL untouched so theIl window is not reset by every concurrent job hitting the linit.Redis::set(ScacheKey, (string) (tine() + SretryAfter).app/Services/Crm/Hubspot/Client.php:183lSthis->log->warning( Hubspot) Received 429 from API'.iteanSdl'configid'= Sthis->config->getido."retry after' => SretryAfter=> Se->getMessageOthrow new RateLinitException message: "Hubspot returned 429'. SretryAfter, Se):Throw Senprivate function getRateLinitCachekey@: strino...o Inu co moy 10:15.4eTextRelayServiceTest+0.A SF fiminny@localhost)8wWAVÁ console (STAGING)D6.00€ANo a-created at> DAT: SUBCMOWOL INTERVAL 3ODAYOIGROUP BY v.id, v.email, u.nane, u.softphone_numberORDER RY sns count783704ДЕBЦЕА-215select * fron teans where id = 1SELECTCONCAT(u.1d, CASE WHEN u.id = t.ouner id THEN • ouner' ELSE ** END) AS user idsa.*t.ouner id FROM social accounts saconsole (PROD) x C Service.php# console fiaumDojminnyv045 A1 A41 У 66 ACachado Codo XoKick of a new proisct. Make chunoe• AND f.crn_provider_id = 'hs_activity_type';E732— 734- 735PARAtT GAAR MANGURAANOid = 1 and id IN ((18688. 13934. 7160):Sid = 7168 order by id desc Linit 10:select * fron teans where id = 1117select * fron activity searches where user_1d = 31054:Pohettendactivity search_filters where activity_search._id TN (88882. 88992)c. Fix Texikelay service TesteC Multi-Picklist Layout DisplaNtietnheetdor10o PodeswiettKwweuname*4 space...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85240
|
NULL
|
0
|
2026-05-28T12:13:46.167630+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970426167_m1.jpg...
|
Slack
|
Vasil Vasilev (DM) - Jiminny Inc - 2 new items - S Vasil Vasilev (DM) - Jiminny Inc - 2 new items - Slack...
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Lukas Kovalik
Today at 11:55:58 AM
11:55 AM
здрасти Васко, може ли един approve
https://github.com/jiminny/app/pull/12136
https://github.com/jiminny/app/pull/12136
Vasil Vasilev
Today at 12:00:25 PM
12:00 PM
Здрасти, Лукаш
Today at 12:00:27 PM
12:00
готов си
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки
Today at 1:25:47 PM
1:25
процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип
Today at 1:26:15 PM...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Later","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Later","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"More…","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"More","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Unreads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Threads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Huddles","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Drafts & sent","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Directories","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-backend-engineers","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-inner-team","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ai-chapter","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"alerts","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"backend","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"bugs","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"confusion-clinic","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"donut_time","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"engineering","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"general","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"happy_birthday","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infosec_internal_all","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infra-changes","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infrastructure_dev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"jbu-team-info","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"jiminny-bg","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"platform-team","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"platform-tickets","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"product_launches","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"random","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"releases","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"support","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"thank-yous","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"the_people_of_jiminny","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Vasil Vasilev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Stefka Stoyanova","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Iliyana Netseva","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Stoyan Tomov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Petko Kashinski","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Galya Dimitrova","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Todor Stamatov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Steliyan Georgiev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Ves","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Mira","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Nikolay Yankov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"James Graham","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Lukas Kovalik","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"you","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Jira Cloud","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Toast","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Google Calendar","depth":15,"bounds":{"left":0.56805557,"top":0.0,"width":0.06388889,"height":0.02},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.56805557,"top":0.0,"width":0.007638889,"height":0.02}},{"char_start":1,"char_count":14,"bounds":{"left":0.57569444,"top":0.0,"width":0.06875,"height":0.02}}],"role_description":"text"},{"role":"AXRadioButton","text":"Messages","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Messages","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Add canvas","depth":10,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Add canvas","depth":12,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Pins","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Pins","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Add and Edit Channel Tabs","depth":9,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Canvas","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"List","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Folder","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Jump to date","depth":14,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 11:55:58 AM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"11:55 AM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"здрасти Васко, може ли един approve","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"https://github.com/jiminny/app/pull/12136","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"https://github.com/jiminny/app/pull/12136","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:25 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Здрасти, Лукаш","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:27 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"готов си","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:37 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"малко по късно и на мен ще ми трябва ревю за един голям feature","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:46 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"но ще ти пиша, като е готов за гледане","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(edited)","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:11:37 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:11 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ок , mersi","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:23:53 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:23 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"като имаш време, разгледай този интересен ПР:","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"https://github.com/jiminny/app/pull/12130","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"https://github.com/jiminny/app/pull/12130","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:25:05 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:25","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:25:47 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:25","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:26:15 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-2193127433489677410
|
-9001319661269969042
|
visual_change
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Lukas Kovalik
Today at 11:55:58 AM
11:55 AM
здрасти Васко, може ли един approve
https://github.com/jiminny/app/pull/12136
https://github.com/jiminny/app/pull/12136
Vasil Vasilev
Today at 12:00:25 PM
12:00 PM
Здрасти, Лукаш
Today at 12:00:27 PM
12:00
готов си
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки
Today at 1:25:47 PM
1:25
процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип
Today at 1:26:15 PM
PhpStormFileEditViewNavigateCodeRefactorRunToolsGitWindowHelpec2-user@ip-10-30-129-190:~881DEV (-zsh)O 82-zshN3screenpipe"O &4DOCKER#_####_#####\###1\#/V~-zsh‹ >0 lol85ec2-user@ip-10-30-129-...100% <78 • Thu 28 May 15:13:46181ec2-user@ip-10-30-140-…..₴7Amazon Linux 2023 (ECS Optimized)For documentation, visit [URL_WITH_CREDENTIALS] ~]$exitlogoutConnection to jiminny-prod-ecs1closed.lukcchiulenWAPS$131PhpStormVersion2023.11.20260505:Version2023.11.20260509:Version 2023.11.20260511:Version 2023.11.20260514:Run "/usr/bin/dnf check-release-update"for full release and version update info#_####_#####\~~###|\#/Amazon Linux 2023 (ECS Optimized)V~m/'For documentation, visit [URL_WITH_CREDENTIALS] ~]$ client_loop: send disconnect: Broken pipeukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-relay) $D...
|
85239
|
NULL
|
NULL
|
NULL
|
|
85239
|
2918
|
70
|
2026-05-28T12:13:40.104549+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970420104_m1.jpg...
|
Slack
|
Vasil Vasilev (DM) - Jiminny Inc - 2 new items - S Vasil Vasilev (DM) - Jiminny Inc - 2 new items - Slack...
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Lukas Kovalik
Today at 11:55:58 AM
11:55 AM
здрасти Васко, може ли един approve
https://github.com/jiminny/app/pull/12136
https://github.com/jiminny/app/pull/12136
Vasil Vasilev
Today at 12:00:25 PM
12:00 PM
Здрасти, Лукаш
Today at 12:00:27 PM
12:00
готов си
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Later","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Later","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"More…","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"More","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Unreads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Threads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Huddles","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Drafts & sent","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Directories","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-backend-engineers","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-inner-team","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ai-chapter","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"alerts","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"backend","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"bugs","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"confusion-clinic","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"donut_time","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"engineering","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"general","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"happy_birthday","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infosec_internal_all","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infra-changes","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infrastructure_dev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"jbu-team-info","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"jiminny-bg","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"platform-team","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"platform-tickets","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"product_launches","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"random","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"releases","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"support","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"thank-yous","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"the_people_of_jiminny","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Vasil Vasilev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Stefka Stoyanova","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Iliyana Netseva","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Stoyan Tomov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Petko Kashinski","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Galya Dimitrova","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Todor Stamatov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Steliyan Georgiev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Ves","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Mira","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Nikolay Yankov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"James Graham","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Lukas Kovalik","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"you","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Jira Cloud","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Toast","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Google Calendar","depth":15,"bounds":{"left":0.56805557,"top":0.0,"width":0.06388889,"height":0.02},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.56805557,"top":0.0,"width":0.007638889,"height":0.02}},{"char_start":1,"char_count":14,"bounds":{"left":0.57569444,"top":0.0,"width":0.06875,"height":0.02}}],"role_description":"text"},{"role":"AXRadioButton","text":"Messages","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Messages","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Add canvas","depth":10,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Add canvas","depth":12,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Pins","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Pins","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Add and Edit Channel Tabs","depth":9,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Canvas","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"List","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Folder","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Jump to date","depth":14,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 11:55:58 AM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"11:55 AM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"здрасти Васко, може ли един approve","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"https://github.com/jiminny/app/pull/12136","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"https://github.com/jiminny/app/pull/12136","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:25 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Здрасти, Лукаш","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:27 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"готов си","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:37 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"малко по късно и на мен ще ми трябва ревю за един голям feature","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:46 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"но ще ти пиша, като е готов за гледане","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(edited)","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:11:37 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:11 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ок , mersi","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:23:53 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:23 PM","depth":16,"on_screen":false,"role_description":"text"}]...
|
-4166503912667803839
|
-8704997394397030546
|
typing_pause
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Lukas Kovalik
Today at 11:55:58 AM
11:55 AM
здрасти Васко, може ли един approve
https://github.com/jiminny/app/pull/12136
https://github.com/jiminny/app/pull/12136
Vasil Vasilev
Today at 12:00:25 PM
12:00 PM
Здрасти, Лукаш
Today at 12:00:27 PM
12:00
готов си
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
PhpStormFileEditViewNavigateCodeRefactorRunToolsGitWindowHelpec2-user@ip-10-30-129-190:~screenpipe"‹$0(ah]БГ100% <78 • Thu 28 May 15:13:40181ec2-user@ip-10-30-140-….₴7DOCKER#_####_#####\\###||\#/V~'881DEV (-zsh)O [EMAIL] Linux 2023 (ECS Optimized)_/m/For documentation, visit [URL_WITH_CREDENTIALS] ~]$ exitlogoutConnection to jiminny-prod-ecsi closed.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ applukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ vprodWarning: Permanently added 'jiminny-prod-ecs1' (ED25519) to the list of known hosts.A newer release of "Amazon Linux" is available.Version 2023.10.20260330:Version 2023.11.20260406:Version 2023.11.20260413:Version2023.11.20260427:Version2023.11.20260505:Version 2023.11.20260509:Version 2023.11.20260511:Version 2023.11.20260514:Run "/usr/bin/dnf check-release-update" for full release and version update info#_~\ ####_\ #####\\###1\#/Amazon Linux 2023 (ECS Optimized)/m/'For documentation, visit [URL_WITH_CREDENTIALS] ~]$ client_loop: send disconnect: Broken pipeukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-relay) $I...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85238
|
NULL
|
0
|
2026-05-28T12:13:39.999535+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970419999_m2.jpg...
|
Slack
|
Vasil Vasilev (DM) - Jiminny Inc - 2 new items - S Vasil Vasilev (DM) - Jiminny Inc - 2 new items - Slack...
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Lukas Kovalik
Today at 11:55:58 AM
11:55 AM
здрасти Васко, може ли един approve
https://github.com/jiminny/app/pull/12136
https://github.com/jiminny/app/pull/12136
Vasil Vasilev
Today at 12:00:25 PM
12:00 PM
Здрасти, Лукаш
Today at 12:00:27 PM
12:00
готов си
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки
Today at 1:25:47 PM
1:25
процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип
Today at 1:26:15 PM
1:26
и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity
Lukas Kovalik
Today at 2:45:12 PM
2:45 PM
Не знам това дали е релевантно
Today at 2:45:14 PM
2:45
1.
Shared Elasticsearch Sockets:
Because
pcntl_fork()
clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in
resetAfterFork()
(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and
cURL
exceptions.
2.
Supervisor Shutdown Deadlock:
In
reapChildren()
, calling
pcntl_waitpid()
without the
WNOHANG
flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.
(edited)
Today at 2:45:29 PM
2:45
3.
Non-Atomic Redis Locks:
The new
ReindexTargetStatsReporter
checks the lock with
get
and then creates it with
set
. Because the workers are truly parallel, they can both read
null
at the exact same microsecond and both push duplicate metrics to Datadog. This needs to be a single, atomic command (e.g.,
set
with
NX
).
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions
Vasil Vasilev
Today at 2:56:52 PM
2:56 PM
1 e добър коментар,
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions
Today at 2:56:55 PM
2:56
2 е intentional,
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"bounds":{"left":0.5056516,"top":0.058260176,"width":0.011968086,"height":0.028731046},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"bounds":{"left":0.50299203,"top":0.10055866,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"bounds":{"left":0.50664896,"top":0.13806863,"width":0.009973404,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"bounds":{"left":0.50299203,"top":0.15482841,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":8,"bounds":{"left":0.50764626,"top":0.19233839,"width":0.007978723,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":6,"bounds":{"left":0.50299203,"top":0.20909816,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":8,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.012965426,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.0026595744,"height":0.011173184}},{"char_start":1,"char_count":7,"bounds":{"left":0.50764626,"top":0.24660814,"width":0.010638298,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":6,"bounds":{"left":0.50299203,"top":0.26336792,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":8,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0076462766,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5099734,"top":0.3008779,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Later","depth":6,"bounds":{"left":0.50299203,"top":0.31763768,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Later","depth":8,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.008643617,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5093085,"top":0.35514766,"width":0.0066489363,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"More…","depth":6,"bounds":{"left":0.50299203,"top":0.3719074,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"More","depth":8,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.008976064,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.0033244682,"height":0.011173184}},{"char_start":1,"char_count":3,"bounds":{"left":0.5106383,"top":0.4094174,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXStaticText","text":"Unreads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Threads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Huddles","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Drafts & sent","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Directories","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-backend-engineers","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-inner-team","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ai-chapter","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"alerts","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"backend","depth":15,"bounds":{"left":0.5422208,"top":0.09736632,"width":0.018284574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.09736632,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54521275,"top":0.09736632,"width":0.015292553,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"bugs","depth":15,"bounds":{"left":0.5422208,"top":0.11971269,"width":0.010638298,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.11971269,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":3,"bounds":{"left":0.54521275,"top":0.11971269,"width":0.00731383,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"confusion-clinic","depth":15,"bounds":{"left":0.5422208,"top":0.14205906,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.14205906,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54454786,"top":0.14205906,"width":0.032247342,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"donut_time","depth":15,"bounds":{"left":0.5422208,"top":0.16440542,"width":0.025265958,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.16440542,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54521275,"top":0.16440542,"width":0.022273935,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"engineering","depth":15,"bounds":{"left":0.5422208,"top":0.1867518,"width":0.025930852,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.1867518,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":10,"bounds":{"left":0.54488033,"top":0.1867518,"width":0.022938829,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"general","depth":15,"bounds":{"left":0.5422208,"top":0.20909816,"width":0.016289894,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.20909816,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54488033,"top":0.20909816,"width":0.013297873,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"happy_birthday","depth":15,"bounds":{"left":0.5422208,"top":0.23144454,"width":0.033909574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.23144454,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.54521275,"top":0.23144454,"width":0.030917553,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infosec_internal_all","depth":15,"bounds":{"left":0.5422208,"top":0.25379092,"width":0.041888297,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.25379092,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":19,"bounds":{"left":0.54355055,"top":0.25379092,"width":0.040226065,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infra-changes","depth":15,"bounds":{"left":0.5422208,"top":0.27613726,"width":0.029587766,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.27613726,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54355055,"top":0.27613726,"width":0.02825798,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infrastructure_dev","depth":15,"bounds":{"left":0.5422208,"top":0.29848364,"width":0.040226065,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.29848364,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":17,"bounds":{"left":0.54355055,"top":0.29848364,"width":0.038896278,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"jbu-team-info","depth":15,"bounds":{"left":0.5422208,"top":0.32083002,"width":0.029920213,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.32083002,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54355055,"top":0.32083002,"width":0.028590426,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"jiminny-bg","depth":15,"bounds":{"left":0.5422208,"top":0.34317636,"width":0.023271276,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.34317636,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54355055,"top":0.34317636,"width":0.021609042,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"platform-team","depth":15,"bounds":{"left":0.5422208,"top":0.36552274,"width":0.03158245,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.36552274,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54521275,"top":0.36552274,"width":0.028590426,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"platform-tickets","depth":15,"bounds":{"left":0.5422208,"top":0.38786912,"width":0.034906916,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.38786912,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54521275,"top":0.38786912,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"product_launches","depth":15,"bounds":{"left":0.5422208,"top":0.4102155,"width":0.03856383,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.4102155,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54521275,"top":0.4102155,"width":0.03557181,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"random","depth":15,"bounds":{"left":0.5422208,"top":0.43256184,"width":0.016954787,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.43256184,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":5,"bounds":{"left":0.54421544,"top":0.43256184,"width":0.014960106,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"releases","depth":15,"bounds":{"left":0.5422208,"top":0.45490822,"width":0.01761968,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.45490822,"width":0.0016622341,"height":0.014365523}},{"char_start":1,"char_count":7,"bounds":{"left":0.54388297,"top":0.45490822,"width":0.015957447,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"support","depth":15,"bounds":{"left":0.5422208,"top":0.4772546,"width":0.017287234,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.4772546,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54454786,"top":0.4772546,"width":0.01462766,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"thank-yous","depth":15,"bounds":{"left":0.5422208,"top":0.49960095,"width":0.024601065,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.49960095,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54421544,"top":0.49960095,"width":0.022606382,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"the_people_of_jiminny","depth":15,"bounds":{"left":0.5422208,"top":0.5219473,"width":0.045212764,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5219473,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":20,"bounds":{"left":0.54421544,"top":0.5219473,"width":0.04720745,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Vasil Vasilev","depth":15,"bounds":{"left":0.5422208,"top":0.5746209,"width":0.026595745,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5746209,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54521275,"top":0.5746209,"width":0.023271276,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Stefka Stoyanova","depth":15,"bounds":{"left":0.5422208,"top":0.5969673,"width":0.037898935,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5969673,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54488033,"top":0.5969673,"width":0.03523936,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Iliyana Netseva","depth":15,"bounds":{"left":0.5422208,"top":0.61931366,"width":0.03324468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.61931366,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54355055,"top":0.61931366,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Stoyan Tomov","depth":15,"bounds":{"left":0.5422208,"top":0.64166003,"width":0.030917553,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.64166003,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":11,"bounds":{"left":0.54488033,"top":0.64166003,"width":0.027925532,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Petko Kashinski","depth":15,"bounds":{"left":0.5422208,"top":0.6640064,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.6640064,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54521275,"top":0.6640064,"width":0.03158245,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Galya Dimitrova","depth":15,"bounds":{"left":0.5422208,"top":0.6863527,"width":0.03523936,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.6863527,"width":0.003656915,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54587764,"top":0.6863527,"width":0.03158245,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Todor Stamatov","depth":15,"bounds":{"left":0.5422208,"top":0.7086991,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7086991,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.54454786,"top":0.7086991,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Steliyan Georgiev","depth":15,"bounds":{"left":0.5422208,"top":0.7310455,"width":0.038231384,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7310455,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":16,"bounds":{"left":0.54488033,"top":0.7310455,"width":0.03557181,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Ves","depth":15,"bounds":{"left":0.5422208,"top":0.75339186,"width":0.007978723,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.75339186,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":2,"bounds":{"left":0.54521275,"top":0.75339186,"width":0.004986702,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Mira","depth":15,"bounds":{"left":0.5422208,"top":0.77573824,"width":0.010305851,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.77573824,"width":0.004654255,"height":0.014365523}},{"char_start":1,"char_count":3,"bounds":{"left":0.546875,"top":0.77573824,"width":0.005319149,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Nikolay Yankov","depth":15,"bounds":{"left":0.5422208,"top":0.7980846,"width":0.032912236,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7980846,"width":0.0039893617,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.5462101,"top":0.7980846,"width":0.028922873,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"James Graham","depth":15,"bounds":{"left":0.5422208,"top":0.820431,"width":0.031914894,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.820431,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":11,"bounds":{"left":0.54421544,"top":0.820431,"width":0.029920213,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Lukas Kovalik","depth":15,"bounds":{"left":0.5422208,"top":0.8427773,"width":0.029587766,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.8427773,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54488033,"top":0.8427773,"width":0.026928192,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"you","depth":15,"bounds":{"left":0.5744681,"top":0.8427773,"width":0.0063164895,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5744681,"top":0.8427773,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":2,"bounds":{"left":0.5767952,"top":0.8427773,"width":0.0056515955,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Jira Cloud","depth":15,"bounds":{"left":0.5422208,"top":0.8954509,"width":0.021941489,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.8954509,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54421544,"top":0.8954509,"width":0.019946808,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Toast","depth":15,"bounds":{"left":0.5422208,"top":0.91779727,"width":0.011635638,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.91779727,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":4,"bounds":{"left":0.54454786,"top":0.91779727,"width":0.00930851,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Google Calendar","depth":15,"bounds":{"left":0.5422208,"top":0.94014364,"width":0.030585106,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.94014364,"width":0.003656915,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54587764,"top":0.94014364,"width":0.032912236,"height":0.014365523}}],"role_description":"text"},{"role":"AXRadioButton","text":"Messages","depth":9,"bounds":{"left":0.60206115,"top":0.09177973,"width":0.030917553,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Messages","depth":11,"bounds":{"left":0.61136967,"top":0.10055866,"width":0.018949468,"height":0.012769354},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.61136967,"top":0.10055866,"width":0.0039893617,"height":0.012769354}},{"char_start":1,"char_count":7,"bounds":{"left":0.61535907,"top":0.10055866,"width":0.014960106,"height":0.012769354}}],"role_description":"text"},{"role":"AXRadioButton","text":"Add canvas","depth":10,"bounds":{"left":0.63397604,"top":0.09177973,"width":0.034242023,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Add canvas","depth":12,"bounds":{"left":0.64328456,"top":0.10055866,"width":0.022273935,"height":0.012769354},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.64328456,"top":0.10055866,"width":0.0033244682,"height":0.012769354}},{"char_start":1,"char_count":9,"bounds":{"left":0.6462766,"top":0.10055866,"width":0.019281914,"height":0.012769354}}],"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":9,"bounds":{"left":0.66921544,"top":0.09177973,"width":0.020944148,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":11,"bounds":{"left":0.67852396,"top":0.10055866,"width":0.008976064,"height":0.012769354},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Pins","depth":9,"bounds":{"left":0.69148934,"top":0.09177973,"width":0.020279255,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Pins","depth":11,"bounds":{"left":0.70079786,"top":0.10055866,"width":0.00831117,"height":0.012769354},"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Add and Edit Channel Tabs","depth":9,"bounds":{"left":0.71276593,"top":0.09177973,"width":0.010970744,"height":0.030327214},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Canvas","depth":9,"bounds":{"left":0.59640956,"top":0.0518755,"width":0.015957447,"height":0.0007980846},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"List","depth":9,"bounds":{"left":0.59640956,"top":0.0518755,"width":0.007978723,"height":0.0007980846},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Folder","depth":9,"bounds":{"left":0.59640956,"top":0.0518755,"width":0.013962766,"height":0.0007980846},"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Jump to date","depth":14,"bounds":{"left":0.7849069,"top":0.12689546,"width":0.025265958,"height":0.022346368},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 11:55:58 AM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"11:55 AM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"здрасти Васко, може ли един approve","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"https://github.com/jiminny/app/pull/12136","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"https://github.com/jiminny/app/pull/12136","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:25 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Здрасти, Лукаш","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:27 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"готов си","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:37 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"малко по късно и на мен ще ми трябва ревю за един голям feature","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:46 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"но ще ти пиша, като е готов за гледане","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(edited)","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:11:37 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:11 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ок , mersi","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:23:53 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:23 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"като имаш време, разгледай този интересен ПР:","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"https://github.com/jiminny/app/pull/12130","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"https://github.com/jiminny/app/pull/12130","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:25:05 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:25","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:25:47 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:25","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:26:15 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:26","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:12 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Не знам това дали е релевантно","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:14 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1.","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Shared Elasticsearch Sockets:","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Because","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"pcntl_fork()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"resetAfterFork()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"cURL","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"exceptions.","depth":15,"bounds":{"left":0.6180186,"top":0.11572227,"width":0.024933511,"height":0.0071827616},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"2.","depth":15,"bounds":{"left":0.6180186,"top":0.13248204,"width":0.0056515955,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Supervisor Shutdown Deadlock:","depth":15,"bounds":{"left":0.62333775,"top":0.13248204,"width":0.07114362,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"In","depth":15,"bounds":{"left":0.69414896,"top":0.13248204,"width":0.006981383,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"reapChildren()","depth":16,"bounds":{"left":0.70212764,"top":0.1348763,"width":0.033909574,"height":0.011971269},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":", calling","depth":15,"bounds":{"left":0.73703456,"top":0.13248204,"width":0.01761968,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"pcntl_waitpid()","depth":16,"bounds":{"left":0.75598407,"top":0.1348763,"width":0.035904255,"height":0.011971269},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"without the","depth":15,"bounds":{"left":0.7932181,"top":0.13248204,"width":0.02825798,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"WNOHANG","depth":16,"bounds":{"left":0.8224734,"top":0.1348763,"width":0.016954787,"height":0.011971269},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.","depth":15,"bounds":{"left":0.6180186,"top":0.13248204,"width":0.3620346,"height":0.031923383},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"","depth":15,"bounds":{"left":0.9212101,"top":0.15163608,"width":0.0013297872,"height":0.012769354},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"(edited)","depth":15,"bounds":{"left":0.9225399,"top":0.15163608,"width":0.014295213,"height":0.012769354},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"","depth":15,"bounds":{"left":0.93650264,"top":0.15163608,"width":0.0013297872,"height":0.012769354},"on_screen":true,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:29 PM","depth":16,"bounds":{"left":0.60738033,"top":0.1763767,"width":0.007978723,"height":0.011173184},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45","depth":17,"bounds":{"left":0.60738033,"top":0.1763767,"width":0.007978723,"height":0.011173184},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"3.","depth":16,"bounds":{"left":0.6180186,"top":0.17398244,"width":0.0056515955,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Non-Atomic Redis Locks:","depth":16,"bounds":{"left":0.62333775,"top":0.17398244,"width":0.055518616,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"The new","depth":16,"bounds":{"left":0.6788564,"top":0.17398244,"width":0.021276595,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ReindexTargetStatsReporter","depth":17,"bounds":{"left":0.70146275,"top":0.1763767,"width":0.06216755,"height":0.011971269},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"checks the lock with","depth":16,"bounds":{"left":0.7649601,"top":0.17398244,"width":0.04720745,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"get","depth":17,"bounds":{"left":0.8131649,"top":0.1763767,"width":0.00731383,"height":0.011971269},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"and then creates it with","depth":16,"bounds":{"left":0.8218085,"top":0.17398244,"width":0.05418883,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"set","depth":17,"bounds":{"left":0.87699467,"top":0.1763767,"width":0.00731383,"height":0.011971269},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":". Because the workers are truly parallel, they can both read","depth":16,"bounds":{"left":0.6180186,"top":0.17398244,"width":0.37300533,"height":0.031923383},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"null","depth":17,"bounds":{"left":0.64162236,"top":0.19393456,"width":0.009640957,"height":0.011971269},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"at the exact same microsecond and both push duplicate metrics to Datadog. This needs to be a single, atomic command (e.g.,","depth":16,"bounds":{"left":0.6525931,"top":0.1915403,"width":0.27393618,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"set","depth":17,"bounds":{"left":0.9275266,"top":0.19393456,"width":0.00731383,"height":0.011971269},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"with","depth":16,"bounds":{"left":0.9361702,"top":0.1915403,"width":0.012300532,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"NX","depth":17,"bounds":{"left":0.9494681,"top":0.19393456,"width":0.004986702,"height":0.011971269},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":").","depth":16,"bounds":{"left":0.95578456,"top":0.1915403,"width":0.0026595744,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"React with white_check_mark","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with eyes","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with raised_hands","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Add reaction…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Reply in thread","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Forward message…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Save for later","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXPopUpButton","text":"More actions","depth":17,"on_screen":false,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"bounds":{"left":0.6180186,"top":0.21388668,"width":0.027593086,"height":0.017557861},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"bounds":{"left":0.6456117,"top":0.21548285,"width":0.0026595744,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXLink","text":"Today at 2:56:52 PM","depth":15,"bounds":{"left":0.64793885,"top":0.21787709,"width":0.015292553,"height":0.011173184},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:56 PM","depth":16,"bounds":{"left":0.64793885,"top":0.21787709,"width":0.015292553,"height":0.011173184},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1 e добър коментар,","depth":16,"bounds":{"left":0.6180186,"top":0.2330407,"width":0.04720745,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"React with white_check_mark","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with eyes","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with raised_hands","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Add reaction…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Reply in thread","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Forward message…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Save for later","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXPopUpButton","text":"More actions","depth":17,"on_screen":false,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Today at 2:56:55 PM","depth":16,"bounds":{"left":0.60738033,"top":0.25937748,"width":0.007978723,"height":0.011173184},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:56","depth":17,"bounds":{"left":0.60738033,"top":0.25937748,"width":0.007978723,"height":0.011173184},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"2 е intentional,","depth":16,"bounds":{"left":0.6180186,"top":0.25698325,"width":0.032912236,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"React with white_check_mark","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with eyes","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with raised_hands","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Add reaction…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Reply in thread","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Forward message…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Save for later","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXPopUpButton","text":"More actions","depth":17,"on_screen":false,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-7860463507937985201
|
-2155617489272795042
|
typing_pause
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Lukas Kovalik
Today at 11:55:58 AM
11:55 AM
здрасти Васко, може ли един approve
https://github.com/jiminny/app/pull/12136
https://github.com/jiminny/app/pull/12136
Vasil Vasilev
Today at 12:00:25 PM
12:00 PM
Здрасти, Лукаш
Today at 12:00:27 PM
12:00
готов си
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки
Today at 1:25:47 PM
1:25
процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип
Today at 1:26:15 PM
1:26
и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity
Lukas Kovalik
Today at 2:45:12 PM
2:45 PM
Не знам това дали е релевантно
Today at 2:45:14 PM
2:45
1.
Shared Elasticsearch Sockets:
Because
pcntl_fork()
clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in
resetAfterFork()
(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and
cURL
exceptions.
2.
Supervisor Shutdown Deadlock:
In
reapChildren()
, calling
pcntl_waitpid()
without the
WNOHANG
flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.
(edited)
Today at 2:45:29 PM
2:45
3.
Non-Atomic Redis Locks:
The new
ReindexTargetStatsReporter
checks the lock with
get
and then creates it with
set
. Because the workers are truly parallel, they can both read
null
at the exact same microsecond and both push duplicate metrics to Datadog. This needs to be a single, atomic command (e.g.,
set
with
NX
).
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions
Vasil Vasilev
Today at 2:56:52 PM
2:56 PM
1 e добър коментар,
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions
Today at 2:56:55 PM
2:56
2 е intentional,
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions
sluckcolVIChRotonWindowHeir• =github.com/v Gooc e GeminiPipelines - jiminny/app(JY-20613) Allow owner's role to bAxUemered tines on New codJY-20963 fix deleted object impJiminny\Exceptions(EmailActivityfrInbox (1,734) - lukas.kovalik Sjlmirnoohye Rosd ve php 81.15 dedPlatform Sorint 5.02 - Platform Te8 Jiminny7 (SRD-6881] (On demand) TransSona Strbramaal an at 27/05/2021aIliyana Netseva at 27/05/2026, 1€) Jy 20910 schedule parallel upc XGemini 3.1 Pro ~That is a very common misconception, but it is not true anymoreWhile it is true that many vears ago around 2014-2016 phpredis had some buas regarding theorder in which EX and NX arguments were passed, it has fully supported combining them into asingle atomic command tor a very long timeTo do this atomically usina the phpredis driver, vou simply pass an associative array of options asthe third argumentHere is exactly how you would write it in your code:PHPSlockKey = sprintf(self::LOCK_KEY, Sthis->updateTarget):/l This executes a single, atomic sat coand with both NX and e)Sacquired = Redis::set(slockkey, true, L'NX, "EX => seLf::LOCK.TTL.SECONDSJ)8if (! Sacquired) &// Another process already holds the lockxeturn.I... report your metrics ...By relying on separate get, set, and expire commands, you are leaving a microsecond gapopen. In your new multi-process Supervisor architecture, two parallel workers can check the get .both see null, and both proceed to write the lock and push duplicate metrics, Usina the arravsyntax above closes that aao completely.A Cleaner laravel AlternativeSince vout are inside a laravel ann vou don't even nopd to ficht with driver-chorifir Redic suntayelcomintYour lim nou chate tehn" uend to imnroy our moddle Camioiie 4l1t cao mata mtake co donbls chack " Yoir oracy & CaminSummarize pageJy 20910 schedule paraCFilter tec.• E app|v = Component/ES|EntityTypeReindexer.phpReindexTargetStatsReporter.p3) UodateProcessManager.phpv Consolev ommande/sacticcaaren• AsyncUpdateEsEntities.php•1AsvncUodateSupervisor.oho- DeleteEmailDocumentsCom…•)ReindexEntityTypes.php•1 RemoveGhostParticipantsCo..8 ResetAsyncElasticSearchCo..2 Kernel.phpv - Contracts/ES|StopSignalinterface.phpv 5 Traits2) GracefullvStonoable.ohov = tests/Unit/Component/ES•) EntityTvpeReindexerTest.php•) ReindexTaroetStatsReporterTes…8 UpdateProcessManagerTest.phpHoeActivityLateMoneiJiminnY ….# backend# buescontusion-dinig# donut_time# engineering# generall# happy_birthdayA infocoe intemal all# infra-chansedPihiesnuen#bu-team-infoi liminnv-benlattormeteam# platform-ticketsworooudauncho# random# released# support# thank-yousthe neonle ortim6? Direct message.Vasil Vasilev. Stefka Stoyanovallivana NetsevaStoyan TomovPetko KashinskiGaiva Dimitrova D: Todor Stamatol1 Stelivan Georsie.Ves&r MireNikolav Vanko&. James GrahamLukas Kovalik y...#:AppsEl tie GloudToastai Gooele Cale.TO0% L7• Thu 28 May 15:13:39@ Describe what you are looking for* €. Vasil Vasileve MessagesNoR0d canvisfiles.2. Supervisor Shutdown Deadlock: In reapChildren®, callins pontl_waitpiilooayt the WNOHANG flag makes it a blockine call. If one child process gets stuck (c.g.waiting on a network timeout), the parent supervisor will freeze indehnitely and completely ignore your 10-second graceful shutdown lozic. (edited3. Non-Atomic Redis Locks: The new ReindexTargetStatsReporter checks the lock with get and then creates it with set. Because the workers are truly parallel, they carboth read null at the exact same microsecond and both push duplicate metrics to Datados. This needs to be a sinale, atomic command (e.?. set with NX)).Vasil Vasilev 2:56 PM1 е добър коментарe intentonaККСНО ФТеелкОлИЕКОФИИИ ОИІКЕЛКУС ОЛОК-ФЬКОТУ-ЕЛТМе ВОТАБОЖЕ БУЙССОХСТАХ ГОНОЯ МОНОМНИ ТОДОВИ АЙТССТЛУСЬНІСЛЕ-ОЛФОНИМИКЯ СТЕОХОЛЕLukas Kovalik 3.07 PMза трстата точка обаче наистина ли няма польожк!аз маи си ти ползвам някьдеили е друг driverVasil Vasilev 3:10 PMне става бех го наплавил така и се симоиtkac Kowaiik 2utniomами и при мен се чумешеVasil Vasilev 3:11 PMpredis поддьржа set(Skey. Svalue. nx' = true, ex =60))connrodis he crareLukas Kovalik 3:51PMтака май не работеше Sresult = Redis-set(StestKey, StestValue 'SX. SHI. "NX": а така ла Sresult = Redis+set(StestKev Stes†Value.[nx.'ex'=> Sыl]):Vasil Vasiley 3411 PvLukas Kovalik 3..2PMне помня вочеVasil Vasilev 3:12 PMооратното може даetkse Kowsll4 242.o1/може и да брькамVacl Vacllev 2.12 pvRkOna uMаSlockAcquired - Redis::set(self::POLLING_LOCKKEY, ison_encode(SlockData), "EX", self::LOCK_TTL_SECONDS, "NX")ЗНАчИ ПЬОКОТО ЗЛБОТИла и в— Aae...
|
85236
|
NULL
|
NULL
|
NULL
|
|
85237
|
2918
|
69
|
2026-05-28T12:13:38.842272+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970418842_m1.jpg...
|
Slack
|
Vasil Vasilev (DM) - Jiminny Inc - 2 new items - S Vasil Vasilev (DM) - Jiminny Inc - 2 new items - Slack...
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Lukas Kovalik
Today at 11:55:58 AM
11:55 AM
здрасти Васко, може ли един approve
https://github.com/jiminny/app/pull/12136
https://github.com/jiminny/app/pull/12136
Vasil Vasilev
Today at 12:00:25 PM
12:00 PM
Здрасти, Лукаш
Today at 12:00:27 PM
12:00
готов си
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки
Today at 1:25:47 PM
1:25
процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип
Today at 1:26:15 PM
1:26
и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity
Lukas Kovalik
Today at 2:45:12 PM
2:45 PM
Не знам това дали е релевантно
Today at 2:45:14 PM
2:45
1.
Shared Elasticsearch Sockets:
Because
pcntl_fork()
clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in
resetAfterFork()
(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and
cURL
exceptions.
2.
Supervisor Shutdown Deadlock:
In
reapChildren()
, calling
pcntl_waitpid()
without the
WNOHANG
flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.
(edited)
Today at 2:45:29 PM
2:45
3.
Non-Atomic Redis Locks:
The new
ReindexTargetStatsReporter
checks the lock with
get
and then creates it with
set
. Because the workers are truly parallel, they can both read
null
at the exact same microsecond and both push duplicate metrics to Datadog. This needs to be a single, atomic command (e.g.,
set
with
NX
).
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions
Vasil Vasilev
Today at 2:56:52 PM
2:56 PM
1 e добър коментар,
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions
Today at 2:56:55 PM
2:56
2 е intentional,
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Later","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Later","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"More…","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"More","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Unreads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Threads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Huddles","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Drafts & sent","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Directories","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-backend-engineers","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-inner-team","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ai-chapter","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"alerts","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"backend","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"bugs","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"confusion-clinic","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"donut_time","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"engineering","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"general","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"happy_birthday","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infosec_internal_all","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infra-changes","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infrastructure_dev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"jbu-team-info","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"jiminny-bg","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"platform-team","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"platform-tickets","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"product_launches","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"random","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"releases","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"support","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"thank-yous","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"the_people_of_jiminny","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Vasil Vasilev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Stefka Stoyanova","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Iliyana Netseva","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Stoyan Tomov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Petko Kashinski","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Galya Dimitrova","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Todor Stamatov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Steliyan Georgiev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Ves","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Mira","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Nikolay Yankov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"James Graham","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Lukas Kovalik","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"you","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Jira Cloud","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Toast","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Google Calendar","depth":15,"bounds":{"left":0.56805557,"top":0.0,"width":0.06388889,"height":0.02},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.56805557,"top":0.0,"width":0.007638889,"height":0.02}},{"char_start":1,"char_count":14,"bounds":{"left":0.57569444,"top":0.0,"width":0.06875,"height":0.02}}],"role_description":"text"},{"role":"AXRadioButton","text":"Messages","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Messages","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Add canvas","depth":10,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Add canvas","depth":12,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Pins","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Pins","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Add and Edit Channel Tabs","depth":9,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Canvas","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"List","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Folder","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Jump to date","depth":14,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 11:55:58 AM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"11:55 AM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"здрасти Васко, може ли един approve","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"https://github.com/jiminny/app/pull/12136","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"https://github.com/jiminny/app/pull/12136","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:25 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Здрасти, Лукаш","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:27 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"готов си","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:37 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"малко по късно и на мен ще ми трябва ревю за един голям feature","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:46 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"но ще ти пиша, като е готов за гледане","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(edited)","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:11:37 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:11 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ок , mersi","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:23:53 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:23 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"като имаш време, разгледай този интересен ПР:","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"https://github.com/jiminny/app/pull/12130","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"https://github.com/jiminny/app/pull/12130","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:25:05 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:25","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:25:47 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:25","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:26:15 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:26","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:12 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Не знам това дали е релевантно","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:14 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1.","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Shared Elasticsearch Sockets:","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Because","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"pcntl_fork()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"resetAfterFork()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"cURL","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"exceptions.","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"2.","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Supervisor Shutdown Deadlock:","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"In","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"reapChildren()","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":", calling","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"pcntl_waitpid()","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"without the","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"WNOHANG","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"(edited)","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:29 PM","depth":16,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45","depth":17,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"3.","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Non-Atomic Redis Locks:","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"The new","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ReindexTargetStatsReporter","depth":17,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"checks the lock with","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"get","depth":17,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"and then creates it with","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"set","depth":17,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":". Because the workers are truly parallel, they can both read","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"null","depth":17,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"at the exact same microsecond and both push duplicate metrics to Datadog. This needs to be a single, atomic command (e.g.,","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"set","depth":17,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"with","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"NX","depth":17,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":").","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"React with white_check_mark","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with eyes","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with raised_hands","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Add reaction…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Reply in thread","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Forward message…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Save for later","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXPopUpButton","text":"More actions","depth":17,"on_screen":false,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXLink","text":"Today at 2:56:52 PM","depth":15,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:56 PM","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1 e добър коментар,","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"React with white_check_mark","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with eyes","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with raised_hands","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Add reaction…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Reply in thread","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Forward message…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Save for later","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXPopUpButton","text":"More actions","depth":17,"on_screen":false,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Today at 2:56:55 PM","depth":16,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:56","depth":17,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"2 е intentional,","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"React with white_check_mark","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with eyes","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with raised_hands","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Add reaction…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Reply in thread","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Forward message…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Save for later","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXPopUpButton","text":"More actions","depth":17,"on_screen":false,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-7860463507937985201
|
-2155617489272795042
|
typing_pause
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Lukas Kovalik
Today at 11:55:58 AM
11:55 AM
здрасти Васко, може ли един approve
https://github.com/jiminny/app/pull/12136
https://github.com/jiminny/app/pull/12136
Vasil Vasilev
Today at 12:00:25 PM
12:00 PM
Здрасти, Лукаш
Today at 12:00:27 PM
12:00
готов си
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки
Today at 1:25:47 PM
1:25
процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип
Today at 1:26:15 PM
1:26
и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity
Lukas Kovalik
Today at 2:45:12 PM
2:45 PM
Не знам това дали е релевантно
Today at 2:45:14 PM
2:45
1.
Shared Elasticsearch Sockets:
Because
pcntl_fork()
clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in
resetAfterFork()
(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and
cURL
exceptions.
2.
Supervisor Shutdown Deadlock:
In
reapChildren()
, calling
pcntl_waitpid()
without the
WNOHANG
flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.
(edited)
Today at 2:45:29 PM
2:45
3.
Non-Atomic Redis Locks:
The new
ReindexTargetStatsReporter
checks the lock with
get
and then creates it with
set
. Because the workers are truly parallel, they can both read
null
at the exact same microsecond and both push duplicate metrics to Datadog. This needs to be a single, atomic command (e.g.,
set
with
NX
).
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions
Vasil Vasilev
Today at 2:56:52 PM
2:56 PM
1 e добър коментар,
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions
Today at 2:56:55 PM
2:56
2 е intentional,
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions
PhpStormFileEditViewNavigateCodeRefactorRunToolsGitWindowHelpec2-user@ip-10-30-129-190:~screenpipe"X4‹$0(ah]БГ100% <78• Thu 28 May 15:13:38181ec2-user@ip-10-30-140-….₴7DOCKER#_####_#####\\###||\#/V~'881DEV (-zsh)O [EMAIL] Linux 2023 (ECS Optimized)_/m/For documentation, visit [URL_WITH_CREDENTIALS] ~]$ exitlogoutConnection to jiminny-prod-ecsi closed.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ applukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ vprodWarning: Permanently added 'jiminny-prod-ecs1' (ED25519) to the list of known hosts.A newer release of "Amazon Linux" is available.Version 2023.10.20260330:Version 2023.11.20260406:Version 2023.11.20260413:Version2023.11.20260427:Version2023.11.20260505:Version 2023.11.20260509:Version 2023.11.20260511:Version 2023.11.20260514:Run "/usr/bin/dnf check-release-update" for full release and version update info#_~\ ####_\ #####\\###1\#/Amazon Linux 2023 (ECS Optimized)/m/'For documentation, visit [URL_WITH_CREDENTIALS] ~]$ client_loop: send disconnect: Broken pipeukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-relay) $I...
|
85235
|
NULL
|
NULL
|
NULL
|
|
85236
|
2919
|
76
|
2026-05-28T12:13:38.738611+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970418738_m2.jpg...
|
Slack
|
Vasil Vasilev (DM) - Jiminny Inc - 2 new items - S Vasil Vasilev (DM) - Jiminny Inc - 2 new items - Slack...
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Lukas Kovalik
Today at 11:55:58 AM
11:55 AM
здрасти Васко, може ли един approve
https://github.com/jiminny/app/pull/12136
https://github.com/jiminny/app/pull/12136
Vasil Vasilev
Today at 12:00:25 PM
12:00 PM
Здрасти, Лукаш
Today at 12:00:27 PM
12:00
готов си
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки
Today at 1:25:47 PM
1:25
процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип
Today at 1:26:15 PM
1:26
и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity
Lukas Kovalik
Today at 2:45:12 PM
2:45 PM
Не знам това дали е релевантно
Today at 2:45:14 PM
2:45
1.
Shared Elasticsearch Sockets:
Because
pcntl_fork()
clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in
resetAfterFork()
(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and
cURL
exceptions.
2.
Supervisor Shutdown Deadlock:
In
reapChildren()
, calling
pcntl_waitpid()
without the
WNOHANG
flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.
(edited)
Today at 2:45:29 PM
2:45
3.
Non-Atomic Redis Locks:
The new
ReindexTargetStatsReporter
checks the lock with
get
and then creates it with
set
. Because the workers are truly parallel, they can both read
null
at the exact same microsecond and both push duplicate metrics to Datadog. This needs to be a single, atomic command (e.g.,
set
with
NX
).
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions
Vasil Vasilev
Today at 2:56:52 PM
2:56 PM
1 e добър коментар,
React with white_check_mark...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"bounds":{"left":0.5056516,"top":0.058260176,"width":0.011968086,"height":0.028731046},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"bounds":{"left":0.50299203,"top":0.10055866,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"bounds":{"left":0.50664896,"top":0.13806863,"width":0.009973404,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"bounds":{"left":0.50299203,"top":0.15482841,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":8,"bounds":{"left":0.50764626,"top":0.19233839,"width":0.007978723,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":6,"bounds":{"left":0.50299203,"top":0.20909816,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":8,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.012965426,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.0026595744,"height":0.011173184}},{"char_start":1,"char_count":7,"bounds":{"left":0.50764626,"top":0.24660814,"width":0.010638298,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":6,"bounds":{"left":0.50299203,"top":0.26336792,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":8,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0076462766,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5099734,"top":0.3008779,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Later","depth":6,"bounds":{"left":0.50299203,"top":0.31763768,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Later","depth":8,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.008643617,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5093085,"top":0.35514766,"width":0.0066489363,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"More…","depth":6,"bounds":{"left":0.50299203,"top":0.3719074,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"More","depth":8,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.008976064,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.0033244682,"height":0.011173184}},{"char_start":1,"char_count":3,"bounds":{"left":0.5106383,"top":0.4094174,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXStaticText","text":"Unreads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Threads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Huddles","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Drafts & sent","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Directories","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-backend-engineers","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-inner-team","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ai-chapter","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"alerts","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"backend","depth":15,"bounds":{"left":0.5422208,"top":0.09736632,"width":0.018284574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.09736632,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54521275,"top":0.09736632,"width":0.015292553,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"bugs","depth":15,"bounds":{"left":0.5422208,"top":0.11971269,"width":0.010638298,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.11971269,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":3,"bounds":{"left":0.54521275,"top":0.11971269,"width":0.00731383,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"confusion-clinic","depth":15,"bounds":{"left":0.5422208,"top":0.14205906,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.14205906,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54454786,"top":0.14205906,"width":0.032247342,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"donut_time","depth":15,"bounds":{"left":0.5422208,"top":0.16440542,"width":0.025265958,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.16440542,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54521275,"top":0.16440542,"width":0.022273935,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"engineering","depth":15,"bounds":{"left":0.5422208,"top":0.1867518,"width":0.025930852,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.1867518,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":10,"bounds":{"left":0.54488033,"top":0.1867518,"width":0.022938829,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"general","depth":15,"bounds":{"left":0.5422208,"top":0.20909816,"width":0.016289894,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.20909816,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54488033,"top":0.20909816,"width":0.013297873,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"happy_birthday","depth":15,"bounds":{"left":0.5422208,"top":0.23144454,"width":0.033909574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.23144454,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.54521275,"top":0.23144454,"width":0.030917553,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infosec_internal_all","depth":15,"bounds":{"left":0.5422208,"top":0.25379092,"width":0.041888297,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.25379092,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":19,"bounds":{"left":0.54355055,"top":0.25379092,"width":0.040226065,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infra-changes","depth":15,"bounds":{"left":0.5422208,"top":0.27613726,"width":0.029587766,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.27613726,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54355055,"top":0.27613726,"width":0.02825798,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infrastructure_dev","depth":15,"bounds":{"left":0.5422208,"top":0.29848364,"width":0.040226065,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.29848364,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":17,"bounds":{"left":0.54355055,"top":0.29848364,"width":0.038896278,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"jbu-team-info","depth":15,"bounds":{"left":0.5422208,"top":0.32083002,"width":0.029920213,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.32083002,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54355055,"top":0.32083002,"width":0.028590426,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"jiminny-bg","depth":15,"bounds":{"left":0.5422208,"top":0.34317636,"width":0.023271276,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.34317636,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54355055,"top":0.34317636,"width":0.021609042,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"platform-team","depth":15,"bounds":{"left":0.5422208,"top":0.36552274,"width":0.03158245,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.36552274,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54521275,"top":0.36552274,"width":0.028590426,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"platform-tickets","depth":15,"bounds":{"left":0.5422208,"top":0.38786912,"width":0.034906916,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.38786912,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54521275,"top":0.38786912,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"product_launches","depth":15,"bounds":{"left":0.5422208,"top":0.4102155,"width":0.03856383,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.4102155,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54521275,"top":0.4102155,"width":0.03557181,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"random","depth":15,"bounds":{"left":0.5422208,"top":0.43256184,"width":0.016954787,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.43256184,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":5,"bounds":{"left":0.54421544,"top":0.43256184,"width":0.014960106,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"releases","depth":15,"bounds":{"left":0.5422208,"top":0.45490822,"width":0.01761968,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.45490822,"width":0.0016622341,"height":0.014365523}},{"char_start":1,"char_count":7,"bounds":{"left":0.54388297,"top":0.45490822,"width":0.015957447,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"support","depth":15,"bounds":{"left":0.5422208,"top":0.4772546,"width":0.017287234,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.4772546,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54454786,"top":0.4772546,"width":0.01462766,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"thank-yous","depth":15,"bounds":{"left":0.5422208,"top":0.49960095,"width":0.024601065,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.49960095,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54421544,"top":0.49960095,"width":0.022606382,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"the_people_of_jiminny","depth":15,"bounds":{"left":0.5422208,"top":0.5219473,"width":0.045212764,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5219473,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":20,"bounds":{"left":0.54421544,"top":0.5219473,"width":0.04720745,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Vasil Vasilev","depth":15,"bounds":{"left":0.5422208,"top":0.5746209,"width":0.026595745,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5746209,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54521275,"top":0.5746209,"width":0.023271276,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Stefka Stoyanova","depth":15,"bounds":{"left":0.5422208,"top":0.5969673,"width":0.037898935,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5969673,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54488033,"top":0.5969673,"width":0.03523936,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Iliyana Netseva","depth":15,"bounds":{"left":0.5422208,"top":0.61931366,"width":0.03324468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.61931366,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54355055,"top":0.61931366,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Stoyan Tomov","depth":15,"bounds":{"left":0.5422208,"top":0.64166003,"width":0.030917553,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.64166003,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":11,"bounds":{"left":0.54488033,"top":0.64166003,"width":0.027925532,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Petko Kashinski","depth":15,"bounds":{"left":0.5422208,"top":0.6640064,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.6640064,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54521275,"top":0.6640064,"width":0.03158245,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Galya Dimitrova","depth":15,"bounds":{"left":0.5422208,"top":0.6863527,"width":0.03523936,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.6863527,"width":0.003656915,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54587764,"top":0.6863527,"width":0.03158245,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Todor Stamatov","depth":15,"bounds":{"left":0.5422208,"top":0.7086991,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7086991,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.54454786,"top":0.7086991,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Steliyan Georgiev","depth":15,"bounds":{"left":0.5422208,"top":0.7310455,"width":0.038231384,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7310455,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":16,"bounds":{"left":0.54488033,"top":0.7310455,"width":0.03557181,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Ves","depth":15,"bounds":{"left":0.5422208,"top":0.75339186,"width":0.007978723,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.75339186,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":2,"bounds":{"left":0.54521275,"top":0.75339186,"width":0.004986702,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Mira","depth":15,"bounds":{"left":0.5422208,"top":0.77573824,"width":0.010305851,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.77573824,"width":0.004654255,"height":0.014365523}},{"char_start":1,"char_count":3,"bounds":{"left":0.546875,"top":0.77573824,"width":0.005319149,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Nikolay Yankov","depth":15,"bounds":{"left":0.5422208,"top":0.7980846,"width":0.032912236,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7980846,"width":0.0039893617,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.5462101,"top":0.7980846,"width":0.028922873,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"James Graham","depth":15,"bounds":{"left":0.5422208,"top":0.820431,"width":0.031914894,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.820431,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":11,"bounds":{"left":0.54421544,"top":0.820431,"width":0.029920213,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Lukas Kovalik","depth":15,"bounds":{"left":0.5422208,"top":0.8427773,"width":0.029587766,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.8427773,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54488033,"top":0.8427773,"width":0.026928192,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"you","depth":15,"bounds":{"left":0.5744681,"top":0.8427773,"width":0.0063164895,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5744681,"top":0.8427773,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":2,"bounds":{"left":0.5767952,"top":0.8427773,"width":0.0056515955,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Jira Cloud","depth":15,"bounds":{"left":0.5422208,"top":0.8954509,"width":0.021941489,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.8954509,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54421544,"top":0.8954509,"width":0.019946808,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Toast","depth":15,"bounds":{"left":0.5422208,"top":0.91779727,"width":0.011635638,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.91779727,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":4,"bounds":{"left":0.54454786,"top":0.91779727,"width":0.00930851,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Google Calendar","depth":15,"bounds":{"left":0.5422208,"top":0.94014364,"width":0.030585106,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.94014364,"width":0.003656915,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54587764,"top":0.94014364,"width":0.032912236,"height":0.014365523}}],"role_description":"text"},{"role":"AXRadioButton","text":"Messages","depth":9,"bounds":{"left":0.60206115,"top":0.09177973,"width":0.030917553,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Messages","depth":11,"bounds":{"left":0.61136967,"top":0.10055866,"width":0.018949468,"height":0.012769354},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.61136967,"top":0.10055866,"width":0.0039893617,"height":0.012769354}},{"char_start":1,"char_count":7,"bounds":{"left":0.61535907,"top":0.10055866,"width":0.014960106,"height":0.012769354}}],"role_description":"text"},{"role":"AXRadioButton","text":"Add canvas","depth":10,"bounds":{"left":0.63397604,"top":0.09177973,"width":0.034242023,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Add canvas","depth":12,"bounds":{"left":0.64328456,"top":0.10055866,"width":0.022273935,"height":0.012769354},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.64328456,"top":0.10055866,"width":0.0033244682,"height":0.012769354}},{"char_start":1,"char_count":9,"bounds":{"left":0.6462766,"top":0.10055866,"width":0.019281914,"height":0.012769354}}],"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":9,"bounds":{"left":0.66921544,"top":0.09177973,"width":0.020944148,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":11,"bounds":{"left":0.67852396,"top":0.10055866,"width":0.008976064,"height":0.012769354},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Pins","depth":9,"bounds":{"left":0.69148934,"top":0.09177973,"width":0.020279255,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Pins","depth":11,"bounds":{"left":0.70079786,"top":0.10055866,"width":0.00831117,"height":0.012769354},"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Add and Edit Channel Tabs","depth":9,"bounds":{"left":0.71276593,"top":0.09177973,"width":0.010970744,"height":0.030327214},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Canvas","depth":9,"bounds":{"left":0.59640956,"top":0.0518755,"width":0.015957447,"height":0.0007980846},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"List","depth":9,"bounds":{"left":0.59640956,"top":0.0518755,"width":0.007978723,"height":0.0007980846},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Folder","depth":9,"bounds":{"left":0.59640956,"top":0.0518755,"width":0.013962766,"height":0.0007980846},"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Jump to date","depth":14,"bounds":{"left":0.7849069,"top":0.12689546,"width":0.025265958,"height":0.022346368},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 11:55:58 AM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"11:55 AM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"здрасти Васко, може ли един approve","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"https://github.com/jiminny/app/pull/12136","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"https://github.com/jiminny/app/pull/12136","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:25 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Здрасти, Лукаш","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:27 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"готов си","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:37 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"малко по късно и на мен ще ми трябва ревю за един голям feature","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:46 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"но ще ти пиша, като е готов за гледане","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(edited)","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:11:37 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:11 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ок , mersi","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:23:53 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:23 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"като имаш време, разгледай този интересен ПР:","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"https://github.com/jiminny/app/pull/12130","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"https://github.com/jiminny/app/pull/12130","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:25:05 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:25","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:25:47 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:25","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:26:15 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:26","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:12 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Не знам това дали е релевантно","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:14 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1.","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Shared Elasticsearch Sockets:","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Because","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"pcntl_fork()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"resetAfterFork()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"cURL","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"exceptions.","depth":15,"bounds":{"left":0.6180186,"top":0.11572227,"width":0.024933511,"height":0.0071827616},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"2.","depth":15,"bounds":{"left":0.6180186,"top":0.13248204,"width":0.0056515955,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Supervisor Shutdown Deadlock:","depth":15,"bounds":{"left":0.62333775,"top":0.13248204,"width":0.07114362,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"In","depth":15,"bounds":{"left":0.69414896,"top":0.13248204,"width":0.006981383,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"reapChildren()","depth":16,"bounds":{"left":0.70212764,"top":0.1348763,"width":0.033909574,"height":0.011971269},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":", calling","depth":15,"bounds":{"left":0.73703456,"top":0.13248204,"width":0.01761968,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"pcntl_waitpid()","depth":16,"bounds":{"left":0.75598407,"top":0.1348763,"width":0.035904255,"height":0.011971269},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"without the","depth":15,"bounds":{"left":0.7932181,"top":0.13248204,"width":0.02825798,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"WNOHANG","depth":16,"bounds":{"left":0.8224734,"top":0.1348763,"width":0.016954787,"height":0.011971269},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.","depth":15,"bounds":{"left":0.6180186,"top":0.13248204,"width":0.3620346,"height":0.031923383},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"","depth":15,"bounds":{"left":0.9212101,"top":0.15163608,"width":0.0013297872,"height":0.012769354},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"(edited)","depth":15,"bounds":{"left":0.9225399,"top":0.15163608,"width":0.014295213,"height":0.012769354},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"","depth":15,"bounds":{"left":0.93650264,"top":0.15163608,"width":0.0013297872,"height":0.012769354},"on_screen":true,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:29 PM","depth":16,"bounds":{"left":0.60738033,"top":0.1763767,"width":0.007978723,"height":0.011173184},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45","depth":17,"bounds":{"left":0.60738033,"top":0.1763767,"width":0.007978723,"height":0.011173184},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"3.","depth":16,"bounds":{"left":0.6180186,"top":0.17398244,"width":0.0056515955,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Non-Atomic Redis Locks:","depth":16,"bounds":{"left":0.62333775,"top":0.17398244,"width":0.055518616,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"The new","depth":16,"bounds":{"left":0.6788564,"top":0.17398244,"width":0.021276595,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ReindexTargetStatsReporter","depth":17,"bounds":{"left":0.70146275,"top":0.1763767,"width":0.06216755,"height":0.011971269},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"checks the lock with","depth":16,"bounds":{"left":0.7649601,"top":0.17398244,"width":0.04720745,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"get","depth":17,"bounds":{"left":0.8131649,"top":0.1763767,"width":0.00731383,"height":0.011971269},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"and then creates it with","depth":16,"bounds":{"left":0.8218085,"top":0.17398244,"width":0.05418883,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"set","depth":17,"bounds":{"left":0.87699467,"top":0.1763767,"width":0.00731383,"height":0.011971269},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":". Because the workers are truly parallel, they can both read","depth":16,"bounds":{"left":0.6180186,"top":0.17398244,"width":0.37300533,"height":0.031923383},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"null","depth":17,"bounds":{"left":0.64162236,"top":0.19393456,"width":0.009640957,"height":0.011971269},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"at the exact same microsecond and both push duplicate metrics to Datadog. This needs to be a single, atomic command (e.g.,","depth":16,"bounds":{"left":0.6525931,"top":0.1915403,"width":0.27393618,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"set","depth":17,"bounds":{"left":0.9275266,"top":0.19393456,"width":0.00731383,"height":0.011971269},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"with","depth":16,"bounds":{"left":0.9361702,"top":0.1915403,"width":0.012300532,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"NX","depth":17,"bounds":{"left":0.9494681,"top":0.19393456,"width":0.004986702,"height":0.011971269},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":").","depth":16,"bounds":{"left":0.95578456,"top":0.1915403,"width":0.0026595744,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"React with white_check_mark","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with eyes","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with raised_hands","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Add reaction…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Reply in thread","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Forward message…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Save for later","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXPopUpButton","text":"More actions","depth":17,"on_screen":false,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"bounds":{"left":0.6180186,"top":0.21388668,"width":0.027593086,"height":0.017557861},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"bounds":{"left":0.6456117,"top":0.21548285,"width":0.0026595744,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXLink","text":"Today at 2:56:52 PM","depth":15,"bounds":{"left":0.64793885,"top":0.21787709,"width":0.015292553,"height":0.011173184},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:56 PM","depth":16,"bounds":{"left":0.64793885,"top":0.21787709,"width":0.015292553,"height":0.011173184},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1 e добър коментар,","depth":16,"bounds":{"left":0.6180186,"top":0.2330407,"width":0.04720745,"height":0.014365523},"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"React with white_check_mark","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
6837300342270539080
|
-2155632929680420226
|
typing_pause
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Lukas Kovalik
Today at 11:55:58 AM
11:55 AM
здрасти Васко, може ли един approve
https://github.com/jiminny/app/pull/12136
https://github.com/jiminny/app/pull/12136
Vasil Vasilev
Today at 12:00:25 PM
12:00 PM
Здрасти, Лукаш
Today at 12:00:27 PM
12:00
готов си
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки
Today at 1:25:47 PM
1:25
процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип
Today at 1:26:15 PM
1:26
и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity
Lukas Kovalik
Today at 2:45:12 PM
2:45 PM
Не знам това дали е релевантно
Today at 2:45:14 PM
2:45
1.
Shared Elasticsearch Sockets:
Because
pcntl_fork()
clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in
resetAfterFork()
(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and
cURL
exceptions.
2.
Supervisor Shutdown Deadlock:
In
reapChildren()
, calling
pcntl_waitpid()
without the
WNOHANG
flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.
(edited)
Today at 2:45:29 PM
2:45
3.
Non-Atomic Redis Locks:
The new
ReindexTargetStatsReporter
checks the lock with
get
and then creates it with
set
. Because the workers are truly parallel, they can both read
null
at the exact same microsecond and both push duplicate metrics to Datadog. This needs to be a single, atomic command (e.g.,
set
with
NX
).
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions
Vasil Vasilev
Today at 2:56:52 PM
2:56 PM
1 e добър коментар,
React with white_check_mark
sluckcolVIChRotonWindowHeir• =github.com/v Gooc e GeminiPipelines - jiminny/app(JY-20613) Allow owner's role to bAxUemered tines on New codJY-20963 fix deleted object impJiminny\Exceptions(EmailActivityfrInbox (1,734) - lukas.kovalik Sjlmirnoohye Rosd ve php 81.15 dedPlatform Sorint 5.02 - Platform Te8 Jiminny7 (SRD-6881] (On demand) TransSona Strbramaal an at 27/05/2021aIliyana Netseva at 27/05/2026, 1€) Jy 20910 schedule parallel upc XGemini 3.1 Pro ~That is a very common misconception, but it is not true anymoreWhile it is true that many vears ago around 2014-2016 phpredis had some buas regarding theorder in which EX and NX arguments were passed, it has fully supported combining them into asingle atomic command tor a very long timeTo do this atomically usina the phpredis driver, vou simply pass an associative array of options asthe third argumentHere is exactly how you would write it in your code:PHPSlockKey = sprintf(self::LOCK_KEY, Sthis->updateTarget):/l This executes a single, atomic sat coand with both NX and e)Sacquired = Redis::set(slockkey, true, L'NX, "EX => seLf::LOCK.TTL.SECONDSJ)8if (! Sacquired) &// Another process already holds the lockxeturn.I... report your metrics ...By relying on separate get, set, and expire commands, you are leaving a microsecond gapopen. In your new multi-process Supervisor architecture, two parallel workers can check the get .both see null, and both proceed to write the lock and push duplicate metrics, Usina the arravsyntax above closes that aao completely.A Cleaner laravel AlternativeSince vout are inside a laravel ann vou don't even nopd to ficht with driver-chorifir Redic suntayelcomintYour lim nou chate tehn" uend to imnroy our moddle Camioiie 4l1t cao mata mtake co donbls chack " Yoir oracy & CaminSummarize pageJy 20910 schedule paraCFilter tec.• E app|v = Component/ES|EntityTypeReindexer.phpReindexTargetStatsReporter.p3) UodateProcessManager.phpv Consolev ommande/sacticcaaren• AsyncUpdateEsEntities.php•1AsvncUodateSupervisor.oho- DeleteEmailDocumentsCom…•)ReindexEntityTypes.php•1 RemoveGhostParticipantsCo..8 ResetAsyncElasticSearchCo..2 Kernel.phpv - Contracts/ES|StopSignalinterface.phpv 5 Traits2) GracefullvStonoable.ohov = tests/Unit/Component/ES•) EntityTvpeReindexerTest.php•) ReindexTaroetStatsReporterTes…8 UpdateProcessManagerTest.phpHoeActivityLateMoneiJiminnY ….# backend# buescontusion-dinig# donut_time# engineering# generall# happy_birthdayA infocoe intemal all# infra-chansedPihiesnuen#bu-team-infoi liminnv-benlattormeteam# platform-ticketsworooudauncho# random# released# support# thank-yousthe neonle ortim6? Direct message.Vasil Vasilev. Stefka Stoyanovallivana NetsevaStoyan TomovPetko KashinskiGaiva Dimitrova D: Todor Stamatol1 Stelivan Georsie.Ves&r MireNikolav Vanko&. James GrahamLukas Kovalik y...#:AppsEl tie GloudToastai Gooele Cale.TO0% L7• Thu 28 May 15:13:38@ Describe what you are looking for* €. Vasil Vasileve MessagesNoR0d canvis7 Files2. Supervisor Shutdown Deadlock: In reapChildren®, callins pontl_waitpiilooayt the WNOHANG flag makes it a blockine call. If one child process gets stuck (c.g.waiting on a network timeout), the parent supervisor will freeze indehnitely and completely ignore your 10-second graceful shutdown lozic. (edited3. Non-Atomic Redis Locks: The new ReindexTargetStatsReporter checks the lock with get and then creates it with set. Because the workers are truly parallel, they carboth read null at the exact same microsecond and both push duplicate metrics to Datados. This needs to be a sinale, atomic command (e.?. set with NX)).Vasil Vasilev 2:56 PM1 е добър коментарe intentonaККСНО ФТеелкОлИЕКОФИИИ ОИІКЕЛКУС ОЛОК-ФЬКОТУ-ЕЛТМе ВОТАБОЖЕ БУЙССОХСТАХ ГОНОЯ МОНОМНИ ТОДОВИ АЙТССТЛУСЬНІСЛЕ-ОЛФОНИМИКЯ СТЕОХОЛЕLukas Kovalik 3.07 PMза трстата точка обаче наистина ли няма польожк!аз маи си ти ползвам някьдеили е друг driverVasil Vasilev 3:10 PMне става бех го наплавил така и се симоиtkac Kowaiik 2utniomами и при мен се чумешеVasil Vasilev 3:11 PMpredis поддьржа set(Skey. Svalue. nx' = true, ex =60))connrodis he crareLukas Kovalik 3:51PMтака май не работеше Sresult = Redis-set(StestKey, StestValue 'SX. SHI. "NX": а така ла Sresult = Redis+set(StestKev Stes†Value.[nx.'ex'=> Sыl]):Vasil Vasiley 3411 PvLukas Kovalik 3..2PMне помня вочеVasil Vasilev 3:12 PMооратното може даetkse Kowsll4 242.o1/може и да брькамVacl Vacllev 2.12 pvRkOna uMаSlockAcquired - Redis::set(self::POLLING_LOCKKEY, ison_encode(SlockData), "EX", self::LOCK_TTL_SECONDS, "NX")ЗНАчИ ПЬОКОТО ЗЛБОТИла и вa— Aae...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85235
|
2918
|
68
|
2026-05-28T12:13:38.272108+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970418272_m1.jpg...
|
Slack
|
Vasil Vasilev (DM) - Jiminny Inc - 2 new items - S Vasil Vasilev (DM) - Jiminny Inc - 2 new items - Slack...
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Lukas Kovalik
Today at 11:55:58 AM
11:55 AM
здрасти Васко, може ли един approve
https://github.com/jiminny/app/pull/12136
https://github.com/jiminny/app/pull/12136
Vasil Vasilev
Today at 12:00:25 PM
12:00 PM
Здрасти, Лукаш
Today at 12:00:27 PM
12:00
готов си
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки
Today at 1:25:47 PM
1:25
процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип
Today at 1:26:15 PM
1:26
и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity
Lukas Kovalik
Today at 2:45:12 PM
2:45 PM
Не знам това дали е релевантно
Today at 2:45:14 PM
2:45
1.
Shared Elasticsearch Sockets:
Because
pcntl_fork()
clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in
resetAfterFork()
(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and
cURL
exceptions.
2.
Supervisor Shutdown Deadlock:
In
reapChildren()
, calling
pcntl_waitpid()
without the
WNOHANG
flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.
(edited)
Today at 2:45:29 PM
2:45
3.
Non-Atomic Redis Locks:
The new
ReindexTargetStatsReporter
checks the lock with
get
and then creates it with...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Later","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Later","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"More…","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"More","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Unreads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Threads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Huddles","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Drafts & sent","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Directories","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-backend-engineers","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-inner-team","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ai-chapter","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"alerts","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"backend","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"bugs","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"confusion-clinic","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"donut_time","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"engineering","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"general","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"happy_birthday","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infosec_internal_all","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infra-changes","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infrastructure_dev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"jbu-team-info","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"jiminny-bg","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"platform-team","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"platform-tickets","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"product_launches","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"random","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"releases","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"support","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"thank-yous","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"the_people_of_jiminny","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Vasil Vasilev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Stefka Stoyanova","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Iliyana Netseva","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Stoyan Tomov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Petko Kashinski","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Galya Dimitrova","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Todor Stamatov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Steliyan Georgiev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Ves","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Mira","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Nikolay Yankov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"James Graham","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Lukas Kovalik","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"you","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Jira Cloud","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Toast","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Google Calendar","depth":15,"bounds":{"left":0.56805557,"top":0.0,"width":0.06388889,"height":0.02},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.56805557,"top":0.0,"width":0.007638889,"height":0.02}},{"char_start":1,"char_count":14,"bounds":{"left":0.57569444,"top":0.0,"width":0.06875,"height":0.02}}],"role_description":"text"},{"role":"AXRadioButton","text":"Messages","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Messages","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Add canvas","depth":10,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Add canvas","depth":12,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Pins","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Pins","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Add and Edit Channel Tabs","depth":9,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Canvas","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"List","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Folder","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Jump to date","depth":14,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 11:55:58 AM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"11:55 AM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"здрасти Васко, може ли един approve","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"https://github.com/jiminny/app/pull/12136","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"https://github.com/jiminny/app/pull/12136","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:25 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Здрасти, Лукаш","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:27 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"готов си","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:37 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"малко по късно и на мен ще ми трябва ревю за един голям feature","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:46 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"но ще ти пиша, като е готов за гледане","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(edited)","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:11:37 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:11 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ок , mersi","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:23:53 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:23 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"като имаш време, разгледай този интересен ПР:","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"https://github.com/jiminny/app/pull/12130","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"https://github.com/jiminny/app/pull/12130","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:25:05 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:25","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:25:47 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:25","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:26:15 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:26","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:12 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Не знам това дали е релевантно","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:14 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1.","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Shared Elasticsearch Sockets:","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Because","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"pcntl_fork()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"resetAfterFork()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"cURL","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"exceptions.","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"2.","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Supervisor Shutdown Deadlock:","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"In","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"reapChildren()","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":", calling","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"pcntl_waitpid()","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"without the","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"WNOHANG","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"(edited)","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:29 PM","depth":16,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45","depth":17,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"3.","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Non-Atomic Redis Locks:","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"The new","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ReindexTargetStatsReporter","depth":17,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"checks the lock with","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"get","depth":17,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"and then creates it with","depth":16,"on_screen":true,"role_description":"text"}]...
|
-3574959044969731999
|
222267879729893998
|
typing_pause
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Lukas Kovalik
Today at 11:55:58 AM
11:55 AM
здрасти Васко, може ли един approve
https://github.com/jiminny/app/pull/12136
https://github.com/jiminny/app/pull/12136
Vasil Vasilev
Today at 12:00:25 PM
12:00 PM
Здрасти, Лукаш
Today at 12:00:27 PM
12:00
готов си
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки
Today at 1:25:47 PM
1:25
процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип
Today at 1:26:15 PM
1:26
и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity
Lukas Kovalik
Today at 2:45:12 PM
2:45 PM
Не знам това дали е релевантно
Today at 2:45:14 PM
2:45
1.
Shared Elasticsearch Sockets:
Because
pcntl_fork()
clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in
resetAfterFork()
(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and
cURL
exceptions.
2.
Supervisor Shutdown Deadlock:
In
reapChildren()
, calling
pcntl_waitpid()
without the
WNOHANG
flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.
(edited)
Today at 2:45:29 PM
2:45
3.
Non-Atomic Redis Locks:
The new
ReindexTargetStatsReporter
checks the lock with
get
and then creates it with
PhpStormFileEditViewNavigateCodeRefactorRunToolsGitWindowHelpec2-user@ip-10-30-129-190:~screenpipe"€ 884‹$0(ah]БГ100% <78• Thu 28 May 15:13:38181ec2-user@ip-10-30-140-….₴7DOCKER#_####_#####\\###||\#/V~'881DEV (-zsh)O [EMAIL] Linux 2023 (ECS Optimized)_/m/For documentation, visit [URL_WITH_CREDENTIALS] ~]$ exitlogoutConnection to jiminny-prod-ecsi closed.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ applukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ vprodWarning: Permanently added 'jiminny-prod-ecs1' (ED25519) to the list of known hosts.A newer release of "Amazon Linux" is available.Version 2023.10.20260330:Version 2023.11.20260406:Version 2023.11.20260413:Version2023.11.20260427:Version2023.11.20260505:Version 2023.11.20260509:Version 2023.11.20260511:Version 2023.11.20260514:Run "/usr/bin/dnf check-release-update" for full release and version update info#_~\ ####_\ #####\\###1\#/Amazon Linux 2023 (ECS Optimized)/m/'For documentation, visit [URL_WITH_CREDENTIALS] ~]$ client_loop: send disconnect: Broken pipeukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-relay) $I...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85234
|
2918
|
67
|
2026-05-28T12:13:37.711586+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970417711_m1.jpg...
|
Slack
|
Vasil Vasilev (DM) - Jiminny Inc - 2 new items - S Vasil Vasilev (DM) - Jiminny Inc - 2 new items - Slack...
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Lukas Kovalik
Today at 11:55:58 AM
11:55 AM
здрасти Васко, може ли един approve
https://github.com/jiminny/app/pull/12136
https://github.com/jiminny/app/pull/12136
Vasil Vasilev
Today at 12:00:25 PM
12:00 PM
Здрасти, Лукаш
Today at 12:00:27 PM
12:00
готов си
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки
Today at 1:25:47 PM
1:25
процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип
Today at 1:26:15 PM
1:26
и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity
Lukas Kovalik
Today at 2:45:12 PM
2:45 PM
Не знам това дали е релевантно
Today at 2:45:14 PM
2:45
1.
Shared Elasticsearch Sockets:
Because
pcntl_fork()
clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in
resetAfterFork()
(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and
cURL
exceptions.
2.
Supervisor Shutdown Deadlock:
In
reapChildren()
, calling
pcntl_waitpid()
without the
WNOHANG
flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.
(edited)
Today at 2:45:29 PM
2:45
3.
Non-Atomic Redis Locks:
The new
ReindexTargetStatsReporter
checks the lock with
get
and then creates it with
set
. Because the workers are truly parallel, they can both read
null
at the exact same microsecond and both push duplicate metrics to Datadog. This needs to be a single, atomic command (e.g.,
set
with
NX
).
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions
Vasil Vasilev
Today at 2:56:52 PM
2:56 PM
1 e добър коментар,
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions
Today at 2:56:55 PM
2:56
2 е intentional,
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Later","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Later","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"More…","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"More","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Unreads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Threads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Huddles","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Drafts & sent","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Directories","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-backend-engineers","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-inner-team","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ai-chapter","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"alerts","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"backend","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"bugs","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"confusion-clinic","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"donut_time","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"engineering","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"general","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"happy_birthday","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infosec_internal_all","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infra-changes","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infrastructure_dev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"jbu-team-info","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"jiminny-bg","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"platform-team","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"platform-tickets","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"product_launches","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"random","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"releases","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"support","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"thank-yous","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"the_people_of_jiminny","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Vasil Vasilev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Stefka Stoyanova","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Iliyana Netseva","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Stoyan Tomov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Petko Kashinski","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Galya Dimitrova","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Todor Stamatov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Steliyan Georgiev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Ves","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Mira","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Nikolay Yankov","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"James Graham","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Lukas Kovalik","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"you","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Jira Cloud","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Toast","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Google Calendar","depth":15,"bounds":{"left":0.56805557,"top":0.0,"width":0.06388889,"height":0.02},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.56805557,"top":0.0,"width":0.007638889,"height":0.02}},{"char_start":1,"char_count":14,"bounds":{"left":0.57569444,"top":0.0,"width":0.06875,"height":0.02}}],"role_description":"text"},{"role":"AXRadioButton","text":"Messages","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Messages","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Add canvas","depth":10,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Add canvas","depth":12,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Pins","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Pins","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Add and Edit Channel Tabs","depth":9,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Canvas","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"List","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Folder","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Jump to date","depth":14,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 11:55:58 AM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"11:55 AM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"здрасти Васко, може ли един approve","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"https://github.com/jiminny/app/pull/12136","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"https://github.com/jiminny/app/pull/12136","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:25 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Здрасти, Лукаш","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:27 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"готов си","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:37 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"малко по късно и на мен ще ми трябва ревю за един голям feature","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:46 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"но ще ти пиша, като е готов за гледане","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(edited)","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:11:37 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:11 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ок , mersi","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:23:53 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:23 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"като имаш време, разгледай този интересен ПР:","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"https://github.com/jiminny/app/pull/12130","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"https://github.com/jiminny/app/pull/12130","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:25:05 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:25","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:25:47 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:25","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:26:15 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:26","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:12 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Не знам това дали е релевантно","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:14 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1.","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Shared Elasticsearch Sockets:","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Because","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"pcntl_fork()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"resetAfterFork()","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"cURL","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"exceptions.","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"2.","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Supervisor Shutdown Deadlock:","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"In","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"reapChildren()","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":", calling","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"pcntl_waitpid()","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"without the","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"WNOHANG","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"(edited)","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:29 PM","depth":16,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:45","depth":17,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"3.","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Non-Atomic Redis Locks:","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"The new","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ReindexTargetStatsReporter","depth":17,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"checks the lock with","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"get","depth":17,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"and then creates it with","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"set","depth":17,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":". Because the workers are truly parallel, they can both read","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"null","depth":17,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"at the exact same microsecond and both push duplicate metrics to Datadog. This needs to be a single, atomic command (e.g.,","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"set","depth":17,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"with","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"NX","depth":17,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":").","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"React with white_check_mark","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with eyes","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with raised_hands","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Add reaction…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Reply in thread","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Forward message…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Save for later","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXPopUpButton","text":"More actions","depth":17,"on_screen":false,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXLink","text":"Today at 2:56:52 PM","depth":15,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:56 PM","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1 e добър коментар,","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"React with white_check_mark","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with eyes","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with raised_hands","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Add reaction…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Reply in thread","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Forward message…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Save for later","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXPopUpButton","text":"More actions","depth":17,"on_screen":false,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"Today at 2:56:55 PM","depth":16,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2:56","depth":17,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"2 е intentional,","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXCheckBox","text":"React with white_check_mark","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with eyes","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"React with raised_hands","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Add reaction…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Reply in thread","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Forward message…","depth":17,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Save for later","depth":17,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXPopUpButton","text":"More actions","depth":17,"on_screen":false,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-7860463507937985201
|
-2155617489272795042
|
typing_pause
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Lukas Kovalik
Today at 11:55:58 AM
11:55 AM
здрасти Васко, може ли един approve
https://github.com/jiminny/app/pull/12136
https://github.com/jiminny/app/pull/12136
Vasil Vasilev
Today at 12:00:25 PM
12:00 PM
Здрасти, Лукаш
Today at 12:00:27 PM
12:00
готов си
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки
Today at 1:25:47 PM
1:25
процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип
Today at 1:26:15 PM
1:26
и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity
Lukas Kovalik
Today at 2:45:12 PM
2:45 PM
Не знам това дали е релевантно
Today at 2:45:14 PM
2:45
1.
Shared Elasticsearch Sockets:
Because
pcntl_fork()
clones file descriptors, both child processes will share the exact same HTTP/TCP socket for Elasticsearch. Since you didn’t reset the ES client in
resetAfterFork()
(like you did for Redis and DB), the parallel workers will collide at the network layer, causing corrupted data and
cURL
exceptions.
2.
Supervisor Shutdown Deadlock:
In
reapChildren()
, calling
pcntl_waitpid()
without the
WNOHANG
flag makes it a blocking call. If one child process gets stuck (e.g., waiting on a network timeout), the parent supervisor will freeze indefinitely and completely ignore your 10-second graceful shutdown logic.
(edited)
Today at 2:45:29 PM
2:45
3.
Non-Atomic Redis Locks:
The new
ReindexTargetStatsReporter
checks the lock with
get
and then creates it with
set
. Because the workers are truly parallel, they can both read
null
at the exact same microsecond and both push duplicate metrics to Datadog. This needs to be a single, atomic command (e.g.,
set
with
NX
).
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions
Vasil Vasilev
Today at 2:56:52 PM
2:56 PM
1 e добър коментар,
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions
Today at 2:56:55 PM
2:56
2 е intentional,
React with white_check_mark
React with eyes
React with raised_hands
Add reaction…
Reply in thread
Forward message…
Save for later
More actions
PhpStormFileEditViewNavigateCodeRefactorRunToolsGitWindowHelpec2-user@ip-10-30-129-190:~screenpipe"?84‹$0(ah]БГ100% <78• Thu 28 May 15:13:37181ec2-user@ip-10-30-140-….₴7DOCKER#_####_#####\\###||\#/V~'881DEV (-zsh)O [EMAIL] Linux 2023 (ECS Optimized)_/m/For documentation, visit [URL_WITH_CREDENTIALS] ~]$ exitlogoutConnection to jiminny-prod-ecsi closed.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ applukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ vprodWarning: Permanently added 'jiminny-prod-ecs1' (ED25519) to the list of known hosts.A newer release of "Amazon Linux" is available.Version 2023.10.20260330:Version 2023.11.20260406:Version 2023.11.20260413:Version2023.11.20260427:Version2023.11.20260505:Version 2023.11.20260509:Version 2023.11.20260511:Version 2023.11.20260514:Run "/usr/bin/dnf check-release-update" for full release and version update info#_~\ ####_\ #####\\###1\#/Amazon Linux 2023 (ECS Optimized)/m/'For documentation, visit [URL_WITH_CREDENTIALS] ~]$ client_loop: send disconnect: Broken pipeukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-relay) $I...
|
85231
|
NULL
|
NULL
|
NULL
|
|
85233
|
2919
|
75
|
2026-05-28T12:13:36.983180+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970416983_m2.jpg...
|
Slack
|
Vasil Vasilev (DM) - Jiminny Inc - 2 new items - S Vasil Vasilev (DM) - Jiminny Inc - 2 new items - Slack...
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"bounds":{"left":0.5056516,"top":0.058260176,"width":0.011968086,"height":0.028731046},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"bounds":{"left":0.50299203,"top":0.10055866,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"bounds":{"left":0.50664896,"top":0.13806863,"width":0.009973404,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"bounds":{"left":0.50299203,"top":0.15482841,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":8,"bounds":{"left":0.50764626,"top":0.19233839,"width":0.007978723,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":6,"bounds":{"left":0.50299203,"top":0.20909816,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":8,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.012965426,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.0026595744,"height":0.011173184}},{"char_start":1,"char_count":7,"bounds":{"left":0.50764626,"top":0.24660814,"width":0.010638298,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":6,"bounds":{"left":0.50299203,"top":0.26336792,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":8,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0076462766,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5099734,"top":0.3008779,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Later","depth":6,"bounds":{"left":0.50299203,"top":0.31763768,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Later","depth":8,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.008643617,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5093085,"top":0.35514766,"width":0.0066489363,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"More…","depth":6,"bounds":{"left":0.50299203,"top":0.3719074,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"More","depth":8,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.008976064,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.0033244682,"height":0.011173184}},{"char_start":1,"char_count":3,"bounds":{"left":0.5106383,"top":0.4094174,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXStaticText","text":"Unreads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Threads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Huddles","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Drafts & sent","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Directories","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-backend-engineers","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-inner-team","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ai-chapter","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"alerts","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"backend","depth":15,"bounds":{"left":0.5422208,"top":0.09736632,"width":0.018284574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.09736632,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54521275,"top":0.09736632,"width":0.015292553,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"bugs","depth":15,"bounds":{"left":0.5422208,"top":0.11971269,"width":0.010638298,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.11971269,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":3,"bounds":{"left":0.54521275,"top":0.11971269,"width":0.00731383,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"confusion-clinic","depth":15,"bounds":{"left":0.5422208,"top":0.14205906,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.14205906,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54454786,"top":0.14205906,"width":0.032247342,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"donut_time","depth":15,"bounds":{"left":0.5422208,"top":0.16440542,"width":0.025265958,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.16440542,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54521275,"top":0.16440542,"width":0.022273935,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"engineering","depth":15,"bounds":{"left":0.5422208,"top":0.1867518,"width":0.025930852,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.1867518,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":10,"bounds":{"left":0.54488033,"top":0.1867518,"width":0.022938829,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"general","depth":15,"bounds":{"left":0.5422208,"top":0.20909816,"width":0.016289894,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.20909816,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54488033,"top":0.20909816,"width":0.013297873,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"happy_birthday","depth":15,"bounds":{"left":0.5422208,"top":0.23144454,"width":0.033909574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.23144454,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.54521275,"top":0.23144454,"width":0.030917553,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infosec_internal_all","depth":15,"bounds":{"left":0.5422208,"top":0.25379092,"width":0.041888297,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.25379092,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":19,"bounds":{"left":0.54355055,"top":0.25379092,"width":0.040226065,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infra-changes","depth":15,"bounds":{"left":0.5422208,"top":0.27613726,"width":0.029587766,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.27613726,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54355055,"top":0.27613726,"width":0.02825798,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infrastructure_dev","depth":15,"bounds":{"left":0.5422208,"top":0.29848364,"width":0.040226065,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.29848364,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":17,"bounds":{"left":0.54355055,"top":0.29848364,"width":0.038896278,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"jbu-team-info","depth":15,"bounds":{"left":0.5422208,"top":0.32083002,"width":0.029920213,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.32083002,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54355055,"top":0.32083002,"width":0.028590426,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"jiminny-bg","depth":15,"bounds":{"left":0.5422208,"top":0.34317636,"width":0.023271276,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.34317636,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54355055,"top":0.34317636,"width":0.021609042,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"platform-team","depth":15,"bounds":{"left":0.5422208,"top":0.36552274,"width":0.03158245,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.36552274,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54521275,"top":0.36552274,"width":0.028590426,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"platform-tickets","depth":15,"bounds":{"left":0.5422208,"top":0.38786912,"width":0.034906916,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.38786912,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54521275,"top":0.38786912,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"product_launches","depth":15,"bounds":{"left":0.5422208,"top":0.4102155,"width":0.03856383,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.4102155,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54521275,"top":0.4102155,"width":0.03557181,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"random","depth":15,"bounds":{"left":0.5422208,"top":0.43256184,"width":0.016954787,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.43256184,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":5,"bounds":{"left":0.54421544,"top":0.43256184,"width":0.014960106,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"releases","depth":15,"bounds":{"left":0.5422208,"top":0.45490822,"width":0.01761968,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.45490822,"width":0.0016622341,"height":0.014365523}},{"char_start":1,"char_count":7,"bounds":{"left":0.54388297,"top":0.45490822,"width":0.015957447,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"support","depth":15,"bounds":{"left":0.5422208,"top":0.4772546,"width":0.017287234,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.4772546,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54454786,"top":0.4772546,"width":0.01462766,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"thank-yous","depth":15,"bounds":{"left":0.5422208,"top":0.49960095,"width":0.024601065,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.49960095,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54421544,"top":0.49960095,"width":0.022606382,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"the_people_of_jiminny","depth":15,"bounds":{"left":0.5422208,"top":0.5219473,"width":0.045212764,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5219473,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":20,"bounds":{"left":0.54421544,"top":0.5219473,"width":0.04720745,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Vasil Vasilev","depth":15,"bounds":{"left":0.5422208,"top":0.5746209,"width":0.026595745,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5746209,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54521275,"top":0.5746209,"width":0.023271276,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Stefka Stoyanova","depth":15,"bounds":{"left":0.5422208,"top":0.5969673,"width":0.037898935,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5969673,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54488033,"top":0.5969673,"width":0.03523936,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Iliyana Netseva","depth":15,"bounds":{"left":0.5422208,"top":0.61931366,"width":0.03324468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.61931366,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54355055,"top":0.61931366,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Stoyan Tomov","depth":15,"bounds":{"left":0.5422208,"top":0.64166003,"width":0.030917553,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.64166003,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":11,"bounds":{"left":0.54488033,"top":0.64166003,"width":0.027925532,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Petko Kashinski","depth":15,"bounds":{"left":0.5422208,"top":0.6640064,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.6640064,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54521275,"top":0.6640064,"width":0.03158245,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Galya Dimitrova","depth":15,"bounds":{"left":0.5422208,"top":0.6863527,"width":0.03523936,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.6863527,"width":0.003656915,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54587764,"top":0.6863527,"width":0.03158245,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Todor Stamatov","depth":15,"bounds":{"left":0.5422208,"top":0.7086991,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7086991,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.54454786,"top":0.7086991,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Steliyan Georgiev","depth":15,"bounds":{"left":0.5422208,"top":0.7310455,"width":0.038231384,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7310455,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":16,"bounds":{"left":0.54488033,"top":0.7310455,"width":0.03557181,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Ves","depth":15,"bounds":{"left":0.5422208,"top":0.75339186,"width":0.007978723,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.75339186,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":2,"bounds":{"left":0.54521275,"top":0.75339186,"width":0.004986702,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Mira","depth":15,"bounds":{"left":0.5422208,"top":0.77573824,"width":0.010305851,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.77573824,"width":0.004654255,"height":0.014365523}},{"char_start":1,"char_count":3,"bounds":{"left":0.546875,"top":0.77573824,"width":0.005319149,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Nikolay Yankov","depth":15,"bounds":{"left":0.5422208,"top":0.7980846,"width":0.032912236,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7980846,"width":0.0039893617,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.5462101,"top":0.7980846,"width":0.028922873,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"James Graham","depth":15,"bounds":{"left":0.5422208,"top":0.820431,"width":0.031914894,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.820431,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":11,"bounds":{"left":0.54421544,"top":0.820431,"width":0.029920213,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Lukas Kovalik","depth":15,"bounds":{"left":0.5422208,"top":0.8427773,"width":0.029587766,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.8427773,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54488033,"top":0.8427773,"width":0.026928192,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"you","depth":15,"bounds":{"left":0.5744681,"top":0.8427773,"width":0.0063164895,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5744681,"top":0.8427773,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":2,"bounds":{"left":0.5767952,"top":0.8427773,"width":0.0056515955,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Jira Cloud","depth":15,"bounds":{"left":0.5422208,"top":0.8954509,"width":0.021941489,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.8954509,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54421544,"top":0.8954509,"width":0.019946808,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Toast","depth":15,"bounds":{"left":0.5422208,"top":0.91779727,"width":0.011635638,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.91779727,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":4,"bounds":{"left":0.54454786,"top":0.91779727,"width":0.00930851,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Google Calendar","depth":15,"bounds":{"left":0.5422208,"top":0.94014364,"width":0.030585106,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.94014364,"width":0.003656915,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54587764,"top":0.94014364,"width":0.032912236,"height":0.014365523}}],"role_description":"text"},{"role":"AXRadioButton","text":"Messages","depth":9,"bounds":{"left":0.60206115,"top":0.09177973,"width":0.030917553,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Messages","depth":11,"bounds":{"left":0.61136967,"top":0.10055866,"width":0.018949468,"height":0.012769354},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.61136967,"top":0.10055866,"width":0.0039893617,"height":0.012769354}},{"char_start":1,"char_count":7,"bounds":{"left":0.61535907,"top":0.10055866,"width":0.014960106,"height":0.012769354}}],"role_description":"text"},{"role":"AXRadioButton","text":"Add canvas","depth":10,"bounds":{"left":0.63397604,"top":0.09177973,"width":0.034242023,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Add canvas","depth":12,"bounds":{"left":0.64328456,"top":0.10055866,"width":0.022273935,"height":0.012769354},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.64328456,"top":0.10055866,"width":0.0033244682,"height":0.012769354}},{"char_start":1,"char_count":9,"bounds":{"left":0.6462766,"top":0.10055866,"width":0.019281914,"height":0.012769354}}],"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":9,"bounds":{"left":0.66921544,"top":0.09177973,"width":0.020944148,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":11,"bounds":{"left":0.67852396,"top":0.10055866,"width":0.008976064,"height":0.012769354},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Pins","depth":9,"bounds":{"left":0.69148934,"top":0.09177973,"width":0.020279255,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Pins","depth":11,"bounds":{"left":0.70079786,"top":0.10055866,"width":0.00831117,"height":0.012769354},"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Add and Edit Channel Tabs","depth":9,"bounds":{"left":0.71276593,"top":0.09177973,"width":0.010970744,"height":0.030327214},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-6818258437255970566
|
-1195257183862056242
|
typing_pause
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
sluckcolVIChRotonWindowHeir• =github.com/v Gooc e GeminiPipelines - jiminny/app(JY-20613) Allow owner's role to bAxUemered tines on New codJY-20963 fix deleted object impJiminny\Exceptions(EmailActivityfrInbox (1,734) - lukas.kovalik Sjlmirnoohye Rosd ve php 81.15 dedPlatform Sorint 5.02 - Platform Te8 Jiminny7 (SRD-6881] (On demand) TransSona Strbramaal an at 27/05/2021aIliyana Netseva at 27/05/2026, 1€) Jy 20910 schedule parallel upc XGemini 3.1 Pro ~That is a very common misconception, but it is not true anymoreWhile it is true that many vears ago around 2014-2016 phpredis had some buas regarding theorder in which EX and NX arguments were passed, it has fully supported combining them into asingle atomic command tor a very long timeTo do this atomically usina the phpredis driver, vou simply pass an associative array of options asthe third argumentHere is exactly how you would write it in your code:PHPSlockKey = sprintf(self::LOCK_KEY, Sthis->updateTarget):/l This executes a single, atomic sat coand with both NX and e)Sacquired = Redis::set(slockkey, true, L'NX, "EX => seLf::LOCK.TTL.SECONDSJ)8if (! Sacquired) &// Another process already holds the locknetuyn:I... report your metrics ...By relying on separate get, set, and expire commands, you are leaving a microsecond gapopen. In your new multi-process Supervisor architecture, two parallel workers can check the get .both see null, and both proceed to write the lock and push duplicate metrics, Usina the arravsyntax above closes that aao completely.A Cleaner laravel AlternativeSince vout are inside a laravel ann vou don't even nopd to ficht with driver-chorifir Redic suntayelcomintYour lim nou chate tehn" uend to imnroy our moddle Camioiie 4l1t cao mata mtake co donbls chack " Yoir oracy & CaminSummarize pageJy 20910 schedule paraCFilter tec.• E app|v = Component/ES|EntityTypeReindexer.phpReindexTargetStatsReporter.p3) UodateProcessManager.phpv Consolev ommande slactiecaaren• AsyncUpdateEsEntities.php•1AsvncUodateSupervisor.oho- DeleteEmailDocumentsCom…•)ReindexEntityTypes.php•1 RemoveGhostParticipantsCo..8 ResetAsyncElasticSearchCo..2 Kernel.phpv - Contracts/ES|StopSignalinterface.phpv 5 Traits2) GracefullvStonoable.ohov = tests/Unit/Component/ES•) EntityTvpeReindexerTest.php•) ReindexTaroetStatsReporterTes…8 UpdateProcessManagerTest.phpHoeActivityLateMoneiJiminnY …# backend# buescontusion-dinig# donut_time# engineering# generall# happy_birthdayA infocoe intemal all# infra-chansedPihiesnuen#bu-team-infoi liminnv-benlattormeteam# platform-ticketsworooudauncho# random# released# support# thank-yousthe neonle ortim6? Direct message.Vasil Vasilev. Stefka Stoyanovallivana NetsevaStoyan TomovPetko KashinskiGaiva Dimitrova D: Todor Stamator1 Stelivan Georsie.Ves&r MireNikolav Vanko&. James GrahamLukas Kovalik y...#:AppsEl tie GloudToastai Gooele Cale.TO0% L7• Thu 28 May 15:13:36@ Describe what you are looking for* €. Vasil Vasileve MessagesNoR0d canvis7 Files2. Supervisor Shutdown Deadlock: In reapChildren®, callins pontl_waitpiilooayt the WNOHANG flag makes it a blockine call. If one child process gets stuck (c.g.waiting on a network timeout), the parent supervisor will freeze indehnitely and completely ignore your 10-second graceful shutdown lozic. (edited3. Non-Atomic Redis Locks: The new ReindexTargetStatsReporter checks the lock with get and then creates it with set. Because the workers are truly parallel, they carboth read null at the exact same microsecond and both push duplicate metrics to Datados. This needs to be a sinale, atomic command (e.?. set with NX)).Vasil Vasilev 2:56 PM1 е добър коментарe intentonaККСНО ФТеелкОлИЕКОФИИИ ОИІКЕЛКУС ОЛОК-ФЬКОТУ-ЕЛТМе ВОТАБОЖЕ БУЙССОХСТАХ ГОНОЯ МОНОМНИ ТОДОВИ АЙТССТЛУСЬНІСЛЕ-ОЛФОНИМИКЯ СТЕОХОЛЕLukas Kovalik 3.07 PMза трстата точка обаче наистина ли няма польожк!аз маи си ти ползвам някьдеили е друг driverVasil Vasilev 3:10 PMне става, бях го направил така, и се счупиtkac Kowaiik 2utniomами и при мен се чумешеVasil Vasilev 3:11 PMpredis поддьржа set(Skey. Svalue. nx' = truc. ex =60))connrodis he crareLukas Kovalik 3:51PMтака май не работеше Sresult = Redis-set(StestKey, StestValue, 'SX. SHI. "NX"): а така ла Sresult = Redisuset(StestKey StestValue l'nx' 'ex' => Stll)Vasil Vasiley 3411 PvLukas Kovalik 3..2PMне помня вочеVasil Vasilev 3:12 PMооратното може даetkse Kowsll4 242.o1/може и да бръкамVacl Vacllev 2.12 pvRkOna uMаSlockAcquired - Redis::set(self::POLLING_LOCKKEY, ison_encode(SlockData), "EX", self::LOCK_TTL_SECONDS, "NX")ЗНАчИ ПЬОКОТО ЗЛБОТИMessage Vasil Vasiley- Aa...
|
85232
|
NULL
|
NULL
|
NULL
|
|
85232
|
2919
|
74
|
2026-05-28T12:13:35.539+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970415539_m2.jpg...
|
Slack
|
Vasil Vasilev (DM) - Jiminny Inc - 2 new items - S Vasil Vasilev (DM) - Jiminny Inc - 2 new items - Slack...
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Lukas Kovalik
Today at 11:55:58 AM
11:55 AM
здрасти Васко, може ли един approve
https://github.com/jiminny/app/pull/12136
https://github.com/jiminny/app/pull/12136
Vasil Vasilev
Today at 12:00:25 PM
12:00 PM
Здрасти, Лукаш
Today at 12:00:27 PM
12:00
готов си
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки
Today at 1:25:47 PM
1:25
процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип
Today at 1:26:15 PM
1:26
и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity
Lukas Kovalik
Today at 2:45:12 PM...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"bounds":{"left":0.5056516,"top":0.058260176,"width":0.011968086,"height":0.028731046},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"bounds":{"left":0.50299203,"top":0.10055866,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"bounds":{"left":0.50664896,"top":0.13806863,"width":0.009973404,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"bounds":{"left":0.50299203,"top":0.15482841,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":8,"bounds":{"left":0.50764626,"top":0.19233839,"width":0.007978723,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":6,"bounds":{"left":0.50299203,"top":0.20909816,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":8,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.012965426,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.0026595744,"height":0.011173184}},{"char_start":1,"char_count":7,"bounds":{"left":0.50764626,"top":0.24660814,"width":0.010638298,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":6,"bounds":{"left":0.50299203,"top":0.26336792,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":8,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0076462766,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5099734,"top":0.3008779,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Later","depth":6,"bounds":{"left":0.50299203,"top":0.31763768,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Later","depth":8,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.008643617,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5093085,"top":0.35514766,"width":0.0066489363,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"More…","depth":6,"bounds":{"left":0.50299203,"top":0.3719074,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"More","depth":8,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.008976064,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.0033244682,"height":0.011173184}},{"char_start":1,"char_count":3,"bounds":{"left":0.5106383,"top":0.4094174,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXStaticText","text":"Unreads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Threads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Huddles","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Drafts & sent","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Directories","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-backend-engineers","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-inner-team","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ai-chapter","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"alerts","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"backend","depth":15,"bounds":{"left":0.5422208,"top":0.09736632,"width":0.018284574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.09736632,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54521275,"top":0.09736632,"width":0.015292553,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"bugs","depth":15,"bounds":{"left":0.5422208,"top":0.11971269,"width":0.010638298,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.11971269,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":3,"bounds":{"left":0.54521275,"top":0.11971269,"width":0.00731383,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"confusion-clinic","depth":15,"bounds":{"left":0.5422208,"top":0.14205906,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.14205906,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54454786,"top":0.14205906,"width":0.032247342,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"donut_time","depth":15,"bounds":{"left":0.5422208,"top":0.16440542,"width":0.025265958,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.16440542,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54521275,"top":0.16440542,"width":0.022273935,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"engineering","depth":15,"bounds":{"left":0.5422208,"top":0.1867518,"width":0.025930852,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.1867518,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":10,"bounds":{"left":0.54488033,"top":0.1867518,"width":0.022938829,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"general","depth":15,"bounds":{"left":0.5422208,"top":0.20909816,"width":0.016289894,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.20909816,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54488033,"top":0.20909816,"width":0.013297873,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"happy_birthday","depth":15,"bounds":{"left":0.5422208,"top":0.23144454,"width":0.033909574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.23144454,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.54521275,"top":0.23144454,"width":0.030917553,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infosec_internal_all","depth":15,"bounds":{"left":0.5422208,"top":0.25379092,"width":0.041888297,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.25379092,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":19,"bounds":{"left":0.54355055,"top":0.25379092,"width":0.040226065,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infra-changes","depth":15,"bounds":{"left":0.5422208,"top":0.27613726,"width":0.029587766,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.27613726,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54355055,"top":0.27613726,"width":0.02825798,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infrastructure_dev","depth":15,"bounds":{"left":0.5422208,"top":0.29848364,"width":0.040226065,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.29848364,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":17,"bounds":{"left":0.54355055,"top":0.29848364,"width":0.038896278,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"jbu-team-info","depth":15,"bounds":{"left":0.5422208,"top":0.32083002,"width":0.029920213,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.32083002,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54355055,"top":0.32083002,"width":0.028590426,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"jiminny-bg","depth":15,"bounds":{"left":0.5422208,"top":0.34317636,"width":0.023271276,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.34317636,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54355055,"top":0.34317636,"width":0.021609042,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"platform-team","depth":15,"bounds":{"left":0.5422208,"top":0.36552274,"width":0.03158245,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.36552274,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54521275,"top":0.36552274,"width":0.028590426,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"platform-tickets","depth":15,"bounds":{"left":0.5422208,"top":0.38786912,"width":0.034906916,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.38786912,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54521275,"top":0.38786912,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"product_launches","depth":15,"bounds":{"left":0.5422208,"top":0.4102155,"width":0.03856383,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.4102155,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54521275,"top":0.4102155,"width":0.03557181,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"random","depth":15,"bounds":{"left":0.5422208,"top":0.43256184,"width":0.016954787,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.43256184,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":5,"bounds":{"left":0.54421544,"top":0.43256184,"width":0.014960106,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"releases","depth":15,"bounds":{"left":0.5422208,"top":0.45490822,"width":0.01761968,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.45490822,"width":0.0016622341,"height":0.014365523}},{"char_start":1,"char_count":7,"bounds":{"left":0.54388297,"top":0.45490822,"width":0.015957447,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"support","depth":15,"bounds":{"left":0.5422208,"top":0.4772546,"width":0.017287234,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.4772546,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54454786,"top":0.4772546,"width":0.01462766,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"thank-yous","depth":15,"bounds":{"left":0.5422208,"top":0.49960095,"width":0.024601065,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.49960095,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54421544,"top":0.49960095,"width":0.022606382,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"the_people_of_jiminny","depth":15,"bounds":{"left":0.5422208,"top":0.5219473,"width":0.045212764,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5219473,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":20,"bounds":{"left":0.54421544,"top":0.5219473,"width":0.04720745,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Vasil Vasilev","depth":15,"bounds":{"left":0.5422208,"top":0.5746209,"width":0.026595745,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5746209,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54521275,"top":0.5746209,"width":0.023271276,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Stefka Stoyanova","depth":15,"bounds":{"left":0.5422208,"top":0.5969673,"width":0.037898935,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5969673,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54488033,"top":0.5969673,"width":0.03523936,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Iliyana Netseva","depth":15,"bounds":{"left":0.5422208,"top":0.61931366,"width":0.03324468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.61931366,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54355055,"top":0.61931366,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Stoyan Tomov","depth":15,"bounds":{"left":0.5422208,"top":0.64166003,"width":0.030917553,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.64166003,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":11,"bounds":{"left":0.54488033,"top":0.64166003,"width":0.027925532,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Petko Kashinski","depth":15,"bounds":{"left":0.5422208,"top":0.6640064,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.6640064,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54521275,"top":0.6640064,"width":0.03158245,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Galya Dimitrova","depth":15,"bounds":{"left":0.5422208,"top":0.6863527,"width":0.03523936,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.6863527,"width":0.003656915,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54587764,"top":0.6863527,"width":0.03158245,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Todor Stamatov","depth":15,"bounds":{"left":0.5422208,"top":0.7086991,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7086991,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.54454786,"top":0.7086991,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Steliyan Georgiev","depth":15,"bounds":{"left":0.5422208,"top":0.7310455,"width":0.038231384,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7310455,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":16,"bounds":{"left":0.54488033,"top":0.7310455,"width":0.03557181,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Ves","depth":15,"bounds":{"left":0.5422208,"top":0.75339186,"width":0.007978723,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.75339186,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":2,"bounds":{"left":0.54521275,"top":0.75339186,"width":0.004986702,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Mira","depth":15,"bounds":{"left":0.5422208,"top":0.77573824,"width":0.010305851,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.77573824,"width":0.004654255,"height":0.014365523}},{"char_start":1,"char_count":3,"bounds":{"left":0.546875,"top":0.77573824,"width":0.005319149,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Nikolay Yankov","depth":15,"bounds":{"left":0.5422208,"top":0.7980846,"width":0.032912236,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7980846,"width":0.0039893617,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.5462101,"top":0.7980846,"width":0.028922873,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"James Graham","depth":15,"bounds":{"left":0.5422208,"top":0.820431,"width":0.031914894,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.820431,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":11,"bounds":{"left":0.54421544,"top":0.820431,"width":0.029920213,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Lukas Kovalik","depth":15,"bounds":{"left":0.5422208,"top":0.8427773,"width":0.029587766,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.8427773,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54488033,"top":0.8427773,"width":0.026928192,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"you","depth":15,"bounds":{"left":0.5744681,"top":0.8427773,"width":0.0063164895,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5744681,"top":0.8427773,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":2,"bounds":{"left":0.5767952,"top":0.8427773,"width":0.0056515955,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Jira Cloud","depth":15,"bounds":{"left":0.5422208,"top":0.8954509,"width":0.021941489,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.8954509,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54421544,"top":0.8954509,"width":0.019946808,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Toast","depth":15,"bounds":{"left":0.5422208,"top":0.91779727,"width":0.011635638,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.91779727,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":4,"bounds":{"left":0.54454786,"top":0.91779727,"width":0.00930851,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Google Calendar","depth":15,"bounds":{"left":0.5422208,"top":0.94014364,"width":0.030585106,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.94014364,"width":0.003656915,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54587764,"top":0.94014364,"width":0.032912236,"height":0.014365523}}],"role_description":"text"},{"role":"AXRadioButton","text":"Messages","depth":9,"bounds":{"left":0.60206115,"top":0.09177973,"width":0.030917553,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Messages","depth":11,"bounds":{"left":0.61136967,"top":0.10055866,"width":0.018949468,"height":0.012769354},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.61136967,"top":0.10055866,"width":0.0039893617,"height":0.012769354}},{"char_start":1,"char_count":7,"bounds":{"left":0.61535907,"top":0.10055866,"width":0.014960106,"height":0.012769354}}],"role_description":"text"},{"role":"AXRadioButton","text":"Add canvas","depth":10,"bounds":{"left":0.63397604,"top":0.09177973,"width":0.034242023,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Add canvas","depth":12,"bounds":{"left":0.64328456,"top":0.10055866,"width":0.022273935,"height":0.012769354},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.64328456,"top":0.10055866,"width":0.0033244682,"height":0.012769354}},{"char_start":1,"char_count":9,"bounds":{"left":0.6462766,"top":0.10055866,"width":0.019281914,"height":0.012769354}}],"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":9,"bounds":{"left":0.66921544,"top":0.09177973,"width":0.020944148,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":11,"bounds":{"left":0.67852396,"top":0.10055866,"width":0.008976064,"height":0.012769354},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Pins","depth":9,"bounds":{"left":0.69148934,"top":0.09177973,"width":0.020279255,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Pins","depth":11,"bounds":{"left":0.70079786,"top":0.10055866,"width":0.00831117,"height":0.012769354},"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Add and Edit Channel Tabs","depth":9,"bounds":{"left":0.71276593,"top":0.09177973,"width":0.010970744,"height":0.030327214},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Canvas","depth":9,"bounds":{"left":0.59640956,"top":0.0518755,"width":0.015957447,"height":0.0007980846},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"List","depth":9,"bounds":{"left":0.59640956,"top":0.0518755,"width":0.007978723,"height":0.0007980846},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Folder","depth":9,"bounds":{"left":0.59640956,"top":0.0518755,"width":0.013962766,"height":0.0007980846},"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Jump to date","depth":14,"bounds":{"left":0.7849069,"top":0.12689546,"width":0.025265958,"height":0.022346368},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 11:55:58 AM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"11:55 AM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"здрасти Васко, може ли един approve","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"https://github.com/jiminny/app/pull/12136","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"https://github.com/jiminny/app/pull/12136","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:25 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Здрасти, Лукаш","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:27 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"готов си","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:37 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"малко по късно и на мен ще ми трябва ревю за един голям feature","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:46 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"но ще ти пиша, като е готов за гледане","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"(edited)","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:11:37 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:11 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ок , mersi","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Vasil Vasilev","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:23:53 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:23 PM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"като имаш време, разгледай този интересен ПР:","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"https://github.com/jiminny/app/pull/12130","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"https://github.com/jiminny/app/pull/12130","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:25:05 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:25","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:25:47 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:25","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 1:26:15 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1:26","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 2:45:12 PM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
1118188252512153100
|
-9001038186293258370
|
typing_pause
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Lukas Kovalik
Today at 11:55:58 AM
11:55 AM
здрасти Васко, може ли един approve
https://github.com/jiminny/app/pull/12136
https://github.com/jiminny/app/pull/12136
Vasil Vasilev
Today at 12:00:25 PM
12:00 PM
Здрасти, Лукаш
Today at 12:00:27 PM
12:00
готов си
Today at 12:00:37 PM
12:00
малко по късно и на мен ще ми трябва ревю за един голям feature
Today at 12:00:46 PM
12:00
но ще ти пиша, като е готов за гледане
(edited)
Lukas Kovalik
Today at 12:11:37 PM
12:11 PM
ок , mersi
Vasil Vasilev
Today at 1:23:53 PM
1:23 PM
като имаш време, разгледай този интересен ПР:
https://github.com/jiminny/app/pull/12130
https://github.com/jiminny/app/pull/12130
Today at 1:25:05 PM
1:25
написах supervisor клас AsyncUpdateSupervisor, който се пали от supervisorctl, като тоя клас AsyncUpdateSupervisor пуска два паралелни процеса, един за обработка на активита и втори за обработка на сделки
Today at 1:25:47 PM
1:25
процесите са отделни, за да не се борят за място под слънцето в един и също процес, да можем да им мерим поотделно кой колко памет яде, и съответно да нагласяме размера на всеки batch по тип
Today at 1:26:15 PM
1:26
и да не си пречат, когато има данни за индескиране в опашките и за activity и за opportunity
Lukas Kovalik
Today at 2:45:12 PM
sluckcolVIChRotonWindowHeir• =github.com/v Gooc e GeminiPipelines - jiminny/app(JY-20613) Allow owner's role to bAxUemered tines on New codJY-20963 fix deleted object impJiminny\Exceptions(EmailActivityfrInbox (1,734) - lukas.kovalik Sjlmirnoohye Rosd ve php 81.15 dedPlatform Sorint 5.02 - Platform Te8 Jiminny7 (SRD-6881] (On demand) TransSona Strbramaal an at 27/05/2021aIliyana Netsova at 27/05/2026, 18) Jy 20910 schedule parallel upc XGemini 3.1 Pro ~That is a very common misconception, but it is not true anymoreWhile it is true that many vears ago around 2014-2016 phpredis had some buas regarding theorder in which EX and NX arguments were passed, it has fully supported combining them into asingle atomic command tor a very long timeTo do this atomically usina the phpredis driver, vou simply pass an associative array of options asthe third argumentHere is exactly how you would write it in your code:PHPSlockKey = sprintf(self::LOCK_KEY, Sthis->updateTarget):/l This executes a single, atomic sat coand with both NX and e)Sacquired = Redis::set(slockkey, true, L'NX, "EX => seLf::LOCK.TTL.SECONDSJ)8if (! Sacquired) &// Another process already holds the lockxeturn.I... report your metrics ...By relying on separate get, set, and expire commands, you are leaving a microsecond gapopen. In your new multi-process Supervisor architecture, two parallel workers can check the get .both see null, and both proceed to write the lock and push duplicate metrics, Usina the arravsyntax above closes that aao completely.A Cleaner laravel AlternativeSince vout are inside a laravel ann vou don't even nopd to ficht with driver-chorifir Redic suntayelcomintYour lim nou chate tehn" uend to imnroy our moddle Camioiie 4l1t cao mata mtake co donbls chack " Yoir oracy & CaminSummarize pageJy 20910 schedule paraCFilter tec.• E app|v = Component/ESEntityTypeReindexer.phpReindexTargetStatsReporter.p3) UodateProcessManager.phpv Consolev ommande slactiecaaren• AsyncUpdateEsEntities.php•1AsvncUodateSupervisor.oho- DeleteEmailDocumentsCom…•)ReindexEntityTypes.php•1 RemoveGhostParticipantsCo..8 ResetAsyncElasticSearchCo..2 Kernel.phpv - Contracts/ES|StopSignalinterface.phpv 5 Traits2) GracefullvStonoable.ohov = tests/Unit/Component/ES•) EntityTvpeReindexerTest.php•) ReindexTaroetStatsReporterTes…8 UpdateProcessManagerTest.phpHoeActivityLateMoneiJiminnY …# backend# buescontusion-dinig# donut_time# engineering# general# happy_birthdayA infocoe intemal all# infra-chansedPihiesnuen#bu-team-infoi liminnv-benlattormeteam# platform-ticketsworooudauncho# random# released# support# thank-yousthe neonle ortim6? Direct message.Vasil Vasilev. Stefka Stoyanovallivana NetsevaStoyan TomovPetko KashinskiGaiva Dimitrova: Todor Stamator1 Stelivan Georsie.Ves&r MireNikolav Vanko&. James GrahamLukas Kovalik y...#:AppsEl tie GloudToastai Gooele Cale.• Thu 28 May 15:13:35@ Describe what you are looking for* €. Vasil Vasileve MessagesNoR0d canvisFile2. Supervisor Shutdown Deadlock: In reapChildren®, callins pontl_waitpiilooayt the WNOHANG flag makes it a blockine call. If one child process gets stuck (c.g.waiting on a network timeout), the parent supervisor will freeze indehnitely and completely ignore your 10-second graceful shutdown lozic. (edited3. Non-Atomic Redis Locks: The new ReindexTargetStatsReporter checks the lock with get and then creates it with set. Because the workers are truly parallel, they carboth read null at the exact same microsecond and both push duplicate metrics to Datados. This needs to be a sinale, atomic command (e.?. set with NX)).Vasil Vasilev 2:56 PM1 е добър коментарe intentonaККСНО ФТеелкОлИЕКОФИИИ ОИІКЕЛКУС ОЛОК-ФЬКОТУ-ЕЛТМе ВОТАБОЖЕ БУЙССОХСТАХ ГОНОЯ МОНОМНИ ТОДОВИ АЙТССТЛУСЬНІСЛЕ-ОЛФОНИМИКЯ СТЕОХОЛЕLukas Kovalik 3.07 PMаз маи си ти ползвам някьдеили е друг driverVasil Vasilev 3:10 PMне става бех го наплавил така и се симоиtkac Kowaiik 2utniomами и при мен се чумешеVasil Vasilev 3:11 PMpredis поддьржа set(Skey. Svalue. nx' = true, ex =60))Connrodis he craReLukas Kovalik 3a51PNтака май не работеше Sresult = Redis-set(StestKey, StestValue 'SX. SHI. "NX": а така ла Sresult = Redis+set(StestKev Stes†Value.[nx.'ex'=> Sыl]):Vasil Vasiley 3411 PvLukas Kovalik 3..2PMне помня вочеVasil Vasilev 3:12 PMооратното може даetkse Kowsll4 242.o1/може и да брькамVacl Vacllev 2.12 pvRkOna uMаSlockAcquired - Redis::set(self::POLLING_LOCKKEY, ison_encode(SlockData), "EX", self::LOCK_TTL_SECONDS, "NX")ЗНАчИ ПЬОКОТО ЗЛБОТИ— Аa...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85231
|
2918
|
66
|
2026-05-28T12:13:34.309308+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970414309_m1.jpg...
|
Slack
|
Vasil Vasilev (DM) - Jiminny Inc - 2 new items - S Vasil Vasilev (DM) - Jiminny Inc - 2 new items - Slack...
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-7728254436789182889
|
1084668380251765430
|
click
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
PhpStormFileEditViewNavigateCodeRefactorRunToolsGitWindowHelpec2-user@ip-10-30-129-190:~screenpipe"84‹$0(ah]A100% <78• Thu 28 May 15:13:33181ec2-user@ip-10-30-140-...₴7DOCKER#_####_#####\\###||\#/V~'881DEV (-zsh)O [EMAIL] Linux 2023 (ECS Optimized)_/m/For documentation, visit [URL_WITH_CREDENTIALS] ~]$ exitlogoutConnection to jiminny-prod-ecsi closed.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ applukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ vprodWarning: Permanently added 'jiminny-prod-ecs1' (ED25519) to the list of known hosts.A newer release of "Amazon Linux" is available.Version 2023.10.20260330:Version 2023.11.20260406:Version 2023.11.20260413:Version2023.11.20260427:Version2023.11.20260505:Version 2023.11.20260509:Version 2023.11.20260511:Version 2023.11.20260514:Run "/usr/bin/dnf check-release-update" for full release and version update info#_~\ ####_\ #####\\###1\#/Amazon Linux 2023 (ECS Optimized)/m/'For documentation, visit [URL_WITH_CREDENTIALS] ~]$ client_loop: send disconnect: Broken pipeukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-relay) $I...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85230
|
2919
|
73
|
2026-05-28T12:13:34.186641+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970414186_m2.jpg...
|
Slack
|
Vasil Vasilev (DM) - Jiminny Inc - 2 new items - S Vasil Vasilev (DM) - Jiminny Inc - 2 new items - Slack...
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"bounds":{"left":0.5056516,"top":0.058260176,"width":0.011968086,"height":0.028731046},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"bounds":{"left":0.50299203,"top":0.10055866,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"bounds":{"left":0.50664896,"top":0.13806863,"width":0.009973404,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"bounds":{"left":0.50299203,"top":0.15482841,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":8,"bounds":{"left":0.50764626,"top":0.19233839,"width":0.007978723,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":6,"bounds":{"left":0.50299203,"top":0.20909816,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":8,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.012965426,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.0026595744,"height":0.011173184}},{"char_start":1,"char_count":7,"bounds":{"left":0.50764626,"top":0.24660814,"width":0.010638298,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":6,"bounds":{"left":0.50299203,"top":0.26336792,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":8,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0076462766,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5099734,"top":0.3008779,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Later","depth":6,"bounds":{"left":0.50299203,"top":0.31763768,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Later","depth":8,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.008643617,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5093085,"top":0.35514766,"width":0.0066489363,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"More…","depth":6,"bounds":{"left":0.50299203,"top":0.3719074,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"More","depth":8,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.008976064,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.0033244682,"height":0.011173184}},{"char_start":1,"char_count":3,"bounds":{"left":0.5106383,"top":0.4094174,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXStaticText","text":"Unreads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Threads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Huddles","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Drafts & sent","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Directories","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-backend-engineers","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-inner-team","depth":15,"on_screen":false,"role_description":"text"}]...
|
-9164664127350781039
|
-8080490479297806593
|
click
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
sluckcolVIChRotonWindowHeir• =github.com/v Gooc e GeminiPipelines - jiminny/app(JY-20613) Allow owner's role to bxUewredtines on New codJY-20963 fix deleted object impJiminny\Exceptions(EmailActivityfrInbox (1,734) - lukas.kovalik Sjlmiroonye Rosd ve php 81.15 dedPlatform Sorint 5.02 - Platform Te8 Jiminny7 (SRD-6881] (On demand) TransSona Subramaaian at 27/05/202aIliyana Netsova at 27/05/2026, 18) Jy 20910 schedule parallel upc XGemini 3.1 Pro ~That is a very common misconception, but it is not true anymoreWhile it is true that many vears ago around 2014-2016 phpredis had some buas regarding theorder in which EX and NX arguments were passed, it has fully supported combining them into asingle atomic command tor a very long timeTo do this atomically usina the phpredis driver, vou simply pass an associative array of options asthe third argumentHere is exactly how you would write it in your code:PHPSlockKey = sprintf(self::LOCK_KEY, Sthis->updateTarget):/l This executes a single, atomic sat coand with both NX and e)Sacquired = Redis::set(slockkey, true, L'NX, "EX => seLf::LOCK.TTL.SECONDSJ)8if (! Sacquired) &// Another process already holds the locknetuyn:I... report your metrics ...By relying on separate get, set, and expire commands, you are leaving a microsecond gapopen. In your new multi-process Supervisor architecture, two parallel workers can check the get .both see null, and both proceed to write the lock and push duplicate metrics, Usina the arravsyntax above closes that aao completely.A Cleaner laravel AlternativeSince vout are inside a laravel ann vou don't even nopd to ficht with driver-chorifir Redic suntayelcomintYour lim nou chate trhn" uend to imnroy our moddle Camioiie 4l1t cao mata mtake co donbls chack " Yoir oracy & CaminSummarize pageJy 20910 schedule paraCFilter tec.• E app|v = Component/ESEntityTypeReindexer.phpReindexTargetStatsReporter.p3) UodateProcessManager.phpv Consolev ommande slactiecaaren• AsyncUpdateEsEntities.php•1AsvncUodateSupervisor.oho- DeleteEmailDocumentsCom.•)ReindexEntityTypes.php•1 RemoveGhostParticipantsCo.….8 ResetAsyncElasticSearchCo..2 Kernel.phpv - Contracts/ES|StopSignalinterface.phpv 5 Traits2) GracefullvStonoable.ohov = tests/Unit/Component/ES•) EntityTvpeReindexerTest.php•) ReindexTaroetStatsReporterTes…8 UpdateProcessManagerTest.phpHoeActivityLateMoneiJiminnY ….# backend# buescontusion-dinig# donut_time# engineering# generall# happy_birthdayA infocoe intemal all# infra-chansedPihiesnuen#bu-team-infoi liminnv-benlattormeteam# platform-ticketsworooudauncho# random# released# support# thank-yousthe neonle ortim6? Direct message.Vasil Vasilev. Stefka Stoyanovallivana NetsevaStoyan TomovPetko KashinskiGaiva Dimitrova: Todor Stamatol1 Stelivan Georsie.Ves&r MireNikolav Vanko&. James GrahamLukas Kovalik y...#:AppsEl tie GloudToastai Gooele Cale.• Thu 28 May 15:13:33@ Describe what you are looking for* €. Vasil Vasileve MessagesNoR0d canvis7 File2. Supervisor Shutdown Deadlock: In reapChildren®, callins pontl_waitpiilooayt the WNOHANG flag makes it a blockine call. If one child process gets stuck (c.g.waiting on a network timeout), the parent supervisor will freeze indehnitely and completely ignore your 10-second graceful shutdown lozic. (edited3. Non-Atomic Redis Locks: The new ReindexTargetStatsReporter checks the lock with get and then creates it with set. Because the workers are truly parallel, they carboth read null at the exact same microsecond and both push duplicate metrics to Datados. This needs to be a sinale, atomic command (e.?. set with NX)).Vasil Vasilev 2:56 PM1 е добър коментарe intentonaККСНО ФлеелкОлИЕКОФИИИ ОИІКЕЛКУС ОНОК-ФТЬКОТУ-ЕЛТЬе ВОТАБОЖЕ БУЙ ССОХСТАХ ГОНОЯ МОНОМНИ ТОДОВИ АЙТСЯТЛУСЬНІ СЛЕ-ОЛФОНИМИКЯ СЕОХОЛЕLukas Kovalik 3.07 PMаз маи си ти ползвам някьдеили е друг driverVasil Vasilev 3:10 PMне става, бях го направил така, и се счупиtkac Kowaiik 2utniomами и при мен се чумешеVasil Vasilev 3:11 PMpredis поддьржа set(Skey. Svalue. nx' = truc. ex =60))Connrodis he craReLukas Kovalik 3a51PNтака май не работеше Sresult = Redis-set(StestKey, StestValue, 'SX. SHI. "NX"): а така ла Sresult = Redisuset(StestKey StestValue l'nx' 'ex' => Stll)Vasil Vasiley 3411 PvLukas Kovalik 3..2PMне помня вочеVasil Vasilev 3:12 PMооратното може даetkse Kowsll4 242.o1/може и да брькамVacl Vacllev 2.12 pvRkOna uMаSlockAcquired - Redis::set(self::POLLING_LOCKKEY, ison_encode(SlockData), "EX", self::LOCK_TTL_SECONDS, "NX")ЗНАчИ ПЬОКОТО ЗЛБОТИMessage Vasil Vasiley— Аa...
|
85229
|
NULL
|
NULL
|
NULL
|
|
85229
|
2919
|
72
|
2026-05-28T12:13:31.079607+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970411079_m2.jpg...
|
Slack
|
Vasil Vasilev (DM) - Jiminny Inc - 2 new items - S Vasil Vasilev (DM) - Jiminny Inc - 2 new items - Slack...
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Lukas Kovalik
Today at 11:55:58 AM
11:55 AM
здрасти Васко, може ли един approve
https://github.com/jiminny/app/pull/12136
https://github.com/jiminny/app/pull/12136...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"bounds":{"left":0.5056516,"top":0.058260176,"width":0.011968086,"height":0.028731046},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"bounds":{"left":0.50299203,"top":0.10055866,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"bounds":{"left":0.50664896,"top":0.13806863,"width":0.009973404,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"bounds":{"left":0.50299203,"top":0.15482841,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":8,"bounds":{"left":0.50764626,"top":0.19233839,"width":0.007978723,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":6,"bounds":{"left":0.50299203,"top":0.20909816,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":8,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.012965426,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.0026595744,"height":0.011173184}},{"char_start":1,"char_count":7,"bounds":{"left":0.50764626,"top":0.24660814,"width":0.010638298,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":6,"bounds":{"left":0.50299203,"top":0.26336792,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":8,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0076462766,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5099734,"top":0.3008779,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Later","depth":6,"bounds":{"left":0.50299203,"top":0.31763768,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Later","depth":8,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.008643617,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5093085,"top":0.35514766,"width":0.0066489363,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"More…","depth":6,"bounds":{"left":0.50299203,"top":0.3719074,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"More","depth":8,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.008976064,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.0033244682,"height":0.011173184}},{"char_start":1,"char_count":3,"bounds":{"left":0.5106383,"top":0.4094174,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXStaticText","text":"Unreads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Threads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Huddles","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Drafts & sent","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Directories","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-backend-engineers","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-inner-team","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ai-chapter","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"alerts","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"backend","depth":15,"bounds":{"left":0.5422208,"top":0.09736632,"width":0.018284574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.09736632,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54521275,"top":0.09736632,"width":0.015292553,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"bugs","depth":15,"bounds":{"left":0.5422208,"top":0.11971269,"width":0.010638298,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.11971269,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":3,"bounds":{"left":0.54521275,"top":0.11971269,"width":0.00731383,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"confusion-clinic","depth":15,"bounds":{"left":0.5422208,"top":0.14205906,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.14205906,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54454786,"top":0.14205906,"width":0.032247342,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"donut_time","depth":15,"bounds":{"left":0.5422208,"top":0.16440542,"width":0.025265958,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.16440542,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54521275,"top":0.16440542,"width":0.022273935,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"engineering","depth":15,"bounds":{"left":0.5422208,"top":0.1867518,"width":0.025930852,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.1867518,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":10,"bounds":{"left":0.54488033,"top":0.1867518,"width":0.022938829,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"general","depth":15,"bounds":{"left":0.5422208,"top":0.20909816,"width":0.016289894,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.20909816,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54488033,"top":0.20909816,"width":0.013297873,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"happy_birthday","depth":15,"bounds":{"left":0.5422208,"top":0.23144454,"width":0.033909574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.23144454,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.54521275,"top":0.23144454,"width":0.030917553,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infosec_internal_all","depth":15,"bounds":{"left":0.5422208,"top":0.25379092,"width":0.041888297,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.25379092,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":19,"bounds":{"left":0.54355055,"top":0.25379092,"width":0.040226065,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infra-changes","depth":15,"bounds":{"left":0.5422208,"top":0.27613726,"width":0.029587766,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.27613726,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54355055,"top":0.27613726,"width":0.02825798,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infrastructure_dev","depth":15,"bounds":{"left":0.5422208,"top":0.29848364,"width":0.040226065,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.29848364,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":17,"bounds":{"left":0.54355055,"top":0.29848364,"width":0.038896278,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"jbu-team-info","depth":15,"bounds":{"left":0.5422208,"top":0.32083002,"width":0.029920213,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.32083002,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54355055,"top":0.32083002,"width":0.028590426,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"jiminny-bg","depth":15,"bounds":{"left":0.5422208,"top":0.34317636,"width":0.023271276,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.34317636,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54355055,"top":0.34317636,"width":0.021609042,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"platform-team","depth":15,"bounds":{"left":0.5422208,"top":0.36552274,"width":0.03158245,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.36552274,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54521275,"top":0.36552274,"width":0.028590426,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"platform-tickets","depth":15,"bounds":{"left":0.5422208,"top":0.38786912,"width":0.034906916,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.38786912,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54521275,"top":0.38786912,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"product_launches","depth":15,"bounds":{"left":0.5422208,"top":0.4102155,"width":0.03856383,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.4102155,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54521275,"top":0.4102155,"width":0.03557181,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"random","depth":15,"bounds":{"left":0.5422208,"top":0.43256184,"width":0.016954787,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.43256184,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":5,"bounds":{"left":0.54421544,"top":0.43256184,"width":0.014960106,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"releases","depth":15,"bounds":{"left":0.5422208,"top":0.45490822,"width":0.01761968,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.45490822,"width":0.0016622341,"height":0.014365523}},{"char_start":1,"char_count":7,"bounds":{"left":0.54388297,"top":0.45490822,"width":0.015957447,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"support","depth":15,"bounds":{"left":0.5422208,"top":0.4772546,"width":0.017287234,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.4772546,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54454786,"top":0.4772546,"width":0.01462766,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"thank-yous","depth":15,"bounds":{"left":0.5422208,"top":0.49960095,"width":0.024601065,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.49960095,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54421544,"top":0.49960095,"width":0.022606382,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"the_people_of_jiminny","depth":15,"bounds":{"left":0.5422208,"top":0.5219473,"width":0.045212764,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5219473,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":20,"bounds":{"left":0.54421544,"top":0.5219473,"width":0.04720745,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Vasil Vasilev","depth":15,"bounds":{"left":0.5422208,"top":0.5746209,"width":0.026595745,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5746209,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54521275,"top":0.5746209,"width":0.023271276,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Stefka Stoyanova","depth":15,"bounds":{"left":0.5422208,"top":0.5969673,"width":0.037898935,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5969673,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54488033,"top":0.5969673,"width":0.03523936,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Iliyana Netseva","depth":15,"bounds":{"left":0.5422208,"top":0.61931366,"width":0.03324468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.61931366,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54355055,"top":0.61931366,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Stoyan Tomov","depth":15,"bounds":{"left":0.5422208,"top":0.64166003,"width":0.030917553,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.64166003,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":11,"bounds":{"left":0.54488033,"top":0.64166003,"width":0.027925532,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Petko Kashinski","depth":15,"bounds":{"left":0.5422208,"top":0.6640064,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.6640064,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54521275,"top":0.6640064,"width":0.03158245,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Galya Dimitrova","depth":15,"bounds":{"left":0.5422208,"top":0.6863527,"width":0.03523936,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.6863527,"width":0.003656915,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54587764,"top":0.6863527,"width":0.03158245,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Todor Stamatov","depth":15,"bounds":{"left":0.5422208,"top":0.7086991,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7086991,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.54454786,"top":0.7086991,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Steliyan Georgiev","depth":15,"bounds":{"left":0.5422208,"top":0.7310455,"width":0.038231384,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7310455,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":16,"bounds":{"left":0.54488033,"top":0.7310455,"width":0.03557181,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Ves","depth":15,"bounds":{"left":0.5422208,"top":0.75339186,"width":0.007978723,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.75339186,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":2,"bounds":{"left":0.54521275,"top":0.75339186,"width":0.004986702,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Mira","depth":15,"bounds":{"left":0.5422208,"top":0.77573824,"width":0.010305851,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.77573824,"width":0.004654255,"height":0.014365523}},{"char_start":1,"char_count":3,"bounds":{"left":0.546875,"top":0.77573824,"width":0.005319149,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Nikolay Yankov","depth":15,"bounds":{"left":0.5422208,"top":0.7980846,"width":0.032912236,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7980846,"width":0.0039893617,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.5462101,"top":0.7980846,"width":0.028922873,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"James Graham","depth":15,"bounds":{"left":0.5422208,"top":0.820431,"width":0.031914894,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.820431,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":11,"bounds":{"left":0.54421544,"top":0.820431,"width":0.029920213,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Lukas Kovalik","depth":15,"bounds":{"left":0.5422208,"top":0.8427773,"width":0.029587766,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.8427773,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54488033,"top":0.8427773,"width":0.026928192,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"you","depth":15,"bounds":{"left":0.5744681,"top":0.8427773,"width":0.0063164895,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5744681,"top":0.8427773,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":2,"bounds":{"left":0.5767952,"top":0.8427773,"width":0.0056515955,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Jira Cloud","depth":15,"bounds":{"left":0.5422208,"top":0.8954509,"width":0.021941489,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.8954509,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54421544,"top":0.8954509,"width":0.019946808,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Toast","depth":15,"bounds":{"left":0.5422208,"top":0.91779727,"width":0.011635638,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.91779727,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":4,"bounds":{"left":0.54454786,"top":0.91779727,"width":0.00930851,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Google Calendar","depth":15,"bounds":{"left":0.5422208,"top":0.94014364,"width":0.030585106,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.94014364,"width":0.003656915,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54587764,"top":0.94014364,"width":0.032912236,"height":0.014365523}}],"role_description":"text"},{"role":"AXRadioButton","text":"Messages","depth":9,"bounds":{"left":0.60206115,"top":0.09177973,"width":0.030917553,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Messages","depth":11,"bounds":{"left":0.61136967,"top":0.10055866,"width":0.018949468,"height":0.012769354},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.61136967,"top":0.10055866,"width":0.0039893617,"height":0.012769354}},{"char_start":1,"char_count":7,"bounds":{"left":0.61535907,"top":0.10055866,"width":0.014960106,"height":0.012769354}}],"role_description":"text"},{"role":"AXRadioButton","text":"Add canvas","depth":10,"bounds":{"left":0.63397604,"top":0.09177973,"width":0.034242023,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Add canvas","depth":12,"bounds":{"left":0.64328456,"top":0.10055866,"width":0.022273935,"height":0.012769354},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.64328456,"top":0.10055866,"width":0.0033244682,"height":0.012769354}},{"char_start":1,"char_count":9,"bounds":{"left":0.6462766,"top":0.10055866,"width":0.019281914,"height":0.012769354}}],"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":9,"bounds":{"left":0.66921544,"top":0.09177973,"width":0.020944148,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":11,"bounds":{"left":0.67852396,"top":0.10055866,"width":0.008976064,"height":0.012769354},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Pins","depth":9,"bounds":{"left":0.69148934,"top":0.09177973,"width":0.020279255,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Pins","depth":11,"bounds":{"left":0.70079786,"top":0.10055866,"width":0.00831117,"height":0.012769354},"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Add and Edit Channel Tabs","depth":9,"bounds":{"left":0.71276593,"top":0.09177973,"width":0.010970744,"height":0.030327214},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Canvas","depth":9,"bounds":{"left":0.59640956,"top":0.0518755,"width":0.015957447,"height":0.0007980846},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"List","depth":9,"bounds":{"left":0.59640956,"top":0.0518755,"width":0.007978723,"height":0.0007980846},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Folder","depth":9,"bounds":{"left":0.59640956,"top":0.0518755,"width":0.013962766,"height":0.0007980846},"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Jump to date","depth":14,"bounds":{"left":0.7849069,"top":0.12689546,"width":0.025265958,"height":0.022346368},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Lukas Kovalik","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 11:55:58 AM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"11:55 AM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"здрасти Васко, може ли един approve","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"https://github.com/jiminny/app/pull/12136","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"https://github.com/jiminny/app/pull/12136","depth":17,"on_screen":false,"role_description":"text"}]...
|
-2965935725612136479
|
-8198319690845841714
|
visual_change
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Lukas Kovalik
Today at 11:55:58 AM
11:55 AM
здрасти Васко, може ли един approve
https://github.com/jiminny/app/pull/12136
https://github.com/jiminny/app/pull/12136
sluckcolVIChRotonWindowHeir• =github.com/v Gooc e GeminiPipelines - jiminny/app(JY-20613) Allow owner's role to bAxUemered tines on New codJY-20963 fix deleted object impJiminny\Exceptions(EmailActivityfrInbox (1,734) - lukas.kovalik Sjlmiroonye Rosd ve php 81.15 dedPlatform Sorint 5.02 - Platform Te8 Jiminny7 (SRD-6881] (On demand) TransSona Strbramaal an at 27/05/2021aIliyana Netseva at 27/05/2026, 1€) Jy 20910 schedule parallel upc XGemini 3.1 Pro ~That is a very common misconception, but it is not true anymoreWhile it is true that many vears ago around 2014-2016 phpredis had some buas regarding theorder in which EX and NX arguments were passed, it has fully supported combining them into asingle atomic command tor a very long timeTo do this atomically usina the phpredis driver, vou simply pass an associative array of options asthe third argumentHere is exactly how you would write it in your code:PHPSlockKey = sprintf(self::LOCK_KEY, Sthis->updateTarget):/l This executes a single, atomic sat coand with both NX and e)Sacquired = Redis::set(slockkey, true, L'NX, "EX => seLf::LOCK.TTL.SECONDSJ)8if (! Sacquired) &// Another process already holds the lockxeturn.I... report your metrics ...By relying on separate get, set, and expire commands, you are leaving a microsecond gapopen. In your new multi-process Supervisor architecture, two parallel workers can check the get .both see null, and both proceed to write the lock and push duplicate metrics, Usina the arravsyntax above closes that aao completely.A Cleaner laravel AlternativeSince vout are inside a laravel ann vou don't even nopd to ficht with driver-chorifir Redic suntayelcomintYour lim nou chate trhn" uend to imnroy our moddle Camioiie 4l1t cao mata mtake co donbls chack " Yoir oracy & CaminSummarize pageJy 20910 schedule paraCFilter tec.• E app|v = Component/ESEntityTypeReindexer.phpReindexTargetStatsReporter.p3) UodateProcessManager.phpv Consolev ommande slactiecaaren• AsyncUpdateEsEntities.php•1AsvncUodateSupervisor.oho- DeleteEmailDocumentsCom.•)ReindexEntityTypes.php•1 RemoveGhostParticipantsCo.….8 ResetAsyncElasticSearchCo..2 Kernel.phpv - Contracts/ES|StopSignalinterface.phpv 5 Traits2) GracefullvStonoable.ohov = tests/Unit/Component/ES•) EntityTvpeReindexerTest.php•) ReindexTaroetStatsReporterTes…8 UpdateProcessManagerTest.phpHoeActivityLateMoneiJiminnY …# backend# buescontusion-dinig# donut_time# engineering# generall# happy_birthdayA infocoe intemal all# infra-chansedPihiesnuen#bu-team-infoi liminnv-benlattormeteam# platform-ticketsworooudauncho# random# released# support# thank-yousthe neonle ortim6? Direct message.Vasil Vasilev. Stefka Stoyanovallivana NetsevaStoyan TomovPetko KashinskiGaiva Dimitrova D: Todor Stamator1 Stelivan Georsie.Ves&r MireNikolav Vanko¿. James GrahamLukas Kovalik y...#:AppsEl tie GloudToastai Gooele Cale.• Thu 28 May 15:13:30@ Describe what you are looking for* €. Vasil Vasileve MessagesNoR0d canvis7 File2. Supervisor Shutdown Deadlock: In reapChildren®, callins pontl_waitpiilooayt the WNOHANG flag makes it a blockine call. If one child process gets stuck (c.g.waiting on a network timeout), the parent supervisor will freeze indehnitely and completely ignore your 10-second graceful shutdown lozic. (edited3. Non-Atomic Redis Locks: The new ReindexTargetStatsReporter checks the lock with get and then creates it with set. Because the workers are truly parallel, they carboth read null at the exact same microsecond and both push duplicate metrics to Datados. This needs to be a sinale, atomic command (e.?. set with NX)).Vasil Vasilev 2:56 PM1 е добър коментарe intentonaККСНО ФлеелкОлИЕКОФИИИ ОИІКЕЛКУС ОНОК-ФТЬКОТУ-ЕЛТЬе ВОТАБОЖЕ БУЙ ССОХСТАХ ГОНОЯ МОНОМНИ ТОДОВИ АЙТСЯТЛУСЬНІ СЛЕ-ОЛФОНИМИКЯ СЕОХОЛЕLukas Kovalik 3.07 PMза трстата точка обаче наистина ли няма польожк!аз маи си ти ползвам някьдеили е друг driverVasil Vasilev 3:10 PMне става, бях го направил така, и се счупиtkac Kowaiik 2utniomами и при мен се чумешеVasil Vasilev 3:11 PMpredis поддьржа set(Skey. Svalue. nx' = truc. ex =60))connrodis he crareLukas Kovalik 3:51PMтака май не работеше Sresult = Redis-set(StestKey, StestValue, 'SX. SHI. "NX"): а така ла Sresult = Redisuset(StestKey StestValue l'nx' 'ex' => Stll)Vasil Vasiley 3411 PvLukas Kovalik 3..2PMне помня вочеVasil Vasilev 3:12 PMооратното може даetkse Kowsll4 242.o1/може и да бръкамVacl Vacllev 2.12 pvRkOna uMаSlockAcquired - Redis::set(self::POLLING_LOCKKEY, ison_encode(SlockData), "EX", self::LOCK_TTL_SECONDS, "NX")ЗНАчИ ПЬОКОТО ЗЛБОТИMessage Vasil Vasiley- Aa...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85228
|
2919
|
71
|
2026-05-28T12:13:28.049466+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970408049_m2.jpg...
|
Slack
|
Vasil Vasilev (DM) - Jiminny Inc - 2 new items - S Vasil Vasilev (DM) - Jiminny Inc - 2 new items - Slack...
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
rircroxViewhsttonooonnsinsroiuesWindowHelp=github. rircroxViewhsttonooonnsinsroiuesWindowHelp=github.com/iiv Gooc e GeminiPipelines - jiminny/app(JY-20613) Allow owner's role to bAxUemered tines on New codJY-20963 fix deleted object impJiminny\Exceptions(EmailActivityfrInbox (1,734) - lukas.kovalik Sjlmirnoonre Rose ve php 81.15 dedPlatform Sorint 5.02 - Platform Te8 Jiminny7 (SRD-6881] (On demand) TransSona Strbramaal an at 27/05/2021aIliyana Netseva at 27/05/2026, 1€) Jy 20910 schedule parallel upc XGemini 3.1 Pro ~That is a very common misconception, but it is not true anymoreWhile it is true that many vears ago around 2014-2016 phpredis had some buas regarding theorder in which EX and NX arguments were passed, it has fully supported combining them into asingle atomic command tor a very long timeTo do this atomically usina the phpredis driver, vou simply pass an associative array of options asthe third argumentHere is exactly how you would write it in your code:PHPSlockKey = sprintf(self::LOCK_KEY, Sthis->updateTarget):/l This executes a single, atomic sat coand with both NX and e)Sacquired = Redis::set(slockkey, true, L'NX, "EX => seLf::LOCK.TTL-SECONDSJ)8if (! Sacquired) &// Another process already holds the lockxeturn.I... report your metrics ...By relying on separate get, set, and expire commands, you are leaving a microsecond gapopen. In your new multi-process Supervisor architecture, two parallel workers can check the get .both see null, and both proceed to write the lock and oush duplicate metrics. Usina the arraysyntax above closes that aao completely.A Cleaner laravel AlternativeSince vout are inside a laravel ann vou don't even nopd to ficht with driver-chorifir Redic suntayelcomintYour Jiminny chats aren't used to improve our modeis. Gemini is Al. It can make mistakes, so double check it. Your privacy & GeminiSummarize pagei1 OpenJy 20910 schedule parallel update target processing #12130All commits - Vasil-Jiminny wants to merge 65 commits into master from JY-20910-schedule-parallel-update-target-processing ™v app/Component/ES/ReindexTargetStatsReporter.php• Filter hiles.• E app|v = Component/ESEntityTypeReindexer.phpReindexTargetStatsReporter.p3) UodateProcessManager.php~ #i Consolev # Commands/Elasticsearch• AsyncUpdateEsEntities.phpD AsyncUpdateSupervisor.php- DeleteEmailDocumentsCom…•)ReindexEntityTypes.php•1 RemoveGhostParticipantsCo.….8 ResetAsyncElasticSearchCo..* Kernel. php~ # Contracts/ESStopSignalinterface.php~ Ei Traits2) GracefullvStonoable.ohov E tests/Unit/Component/ES•) EntityTvpeReindexerTest.php•) ReindexTaroetStatsReporterTes…8) UpdateProcessManagerTest.php#÷997 7 *V itighight All l Match Case ]Match Diacrisies Whole Words 1 of 1 match Reached top of page, continued from bottomCATMОД( 5/15 viewedAnaiuns approv• class ReindextargetStatsReportenptlvete const ste io .oT, Se mios - roces saneger-lock ;:peshace zessing senvronment = meiti:ouotcunc.consercnvtronsencscrtnosenvtronsencrvohsthis-senvsronment " senvironmentpublic function setUpdateTarget(string SupdateTarget): voidSthis->updateTarget = SupdateTarget:public function report(int SprocessedDocumentsCount): voidsthis->assertConfigured():Datadog:: increment(stats: 'jiminny.es-documents-synced',sanpleRate: 1.value: SprocessedDocumentsCount,SlockKey = sprintf(self::L0CK_KEY, Sthis-oupdateTaroet):1t/1 1snul1(Redisa.aet(SlockKew)))return;Redis::set(Slockkey, true);Redis::expire(SlockKey. self::L0CK_TTL_SECONDS):Sthis->reportMenoryUsage():private function assertConfiqured(): voidif (Sthis->updateTarget === null) ‹100% 142-• Thu 28 May 15:13:27nit review -O ∞) 0+95 sssse ~ Viewed...
|
NULL
|
7917280704125441425
|
NULL
|
visual_change
|
ocr
|
NULL
|
rircroxViewhsttonooonnsinsroiuesWindowHelp=github. rircroxViewhsttonooonnsinsroiuesWindowHelp=github.com/iiv Gooc e GeminiPipelines - jiminny/app(JY-20613) Allow owner's role to bAxUemered tines on New codJY-20963 fix deleted object impJiminny\Exceptions(EmailActivityfrInbox (1,734) - lukas.kovalik Sjlmirnoonre Rose ve php 81.15 dedPlatform Sorint 5.02 - Platform Te8 Jiminny7 (SRD-6881] (On demand) TransSona Strbramaal an at 27/05/2021aIliyana Netseva at 27/05/2026, 1€) Jy 20910 schedule parallel upc XGemini 3.1 Pro ~That is a very common misconception, but it is not true anymoreWhile it is true that many vears ago around 2014-2016 phpredis had some buas regarding theorder in which EX and NX arguments were passed, it has fully supported combining them into asingle atomic command tor a very long timeTo do this atomically usina the phpredis driver, vou simply pass an associative array of options asthe third argumentHere is exactly how you would write it in your code:PHPSlockKey = sprintf(self::LOCK_KEY, Sthis->updateTarget):/l This executes a single, atomic sat coand with both NX and e)Sacquired = Redis::set(slockkey, true, L'NX, "EX => seLf::LOCK.TTL-SECONDSJ)8if (! Sacquired) &// Another process already holds the lockxeturn.I... report your metrics ...By relying on separate get, set, and expire commands, you are leaving a microsecond gapopen. In your new multi-process Supervisor architecture, two parallel workers can check the get .both see null, and both proceed to write the lock and oush duplicate metrics. Usina the arraysyntax above closes that aao completely.A Cleaner laravel AlternativeSince vout are inside a laravel ann vou don't even nopd to ficht with driver-chorifir Redic suntayelcomintYour Jiminny chats aren't used to improve our modeis. Gemini is Al. It can make mistakes, so double check it. Your privacy & GeminiSummarize pagei1 OpenJy 20910 schedule parallel update target processing #12130All commits - Vasil-Jiminny wants to merge 65 commits into master from JY-20910-schedule-parallel-update-target-processing ™v app/Component/ES/ReindexTargetStatsReporter.php• Filter hiles.• E app|v = Component/ESEntityTypeReindexer.phpReindexTargetStatsReporter.p3) UodateProcessManager.php~ #i Consolev # Commands/Elasticsearch• AsyncUpdateEsEntities.phpD AsyncUpdateSupervisor.php- DeleteEmailDocumentsCom…•)ReindexEntityTypes.php•1 RemoveGhostParticipantsCo.….8 ResetAsyncElasticSearchCo..* Kernel. php~ # Contracts/ESStopSignalinterface.php~ Ei Traits2) GracefullvStonoable.ohov E tests/Unit/Component/ES•) EntityTvpeReindexerTest.php•) ReindexTaroetStatsReporterTes…8) UpdateProcessManagerTest.php#÷997 7 *V itighight All l Match Case ]Match Diacrisies Whole Words 1 of 1 match Reached top of page, continued from bottomCATMОД( 5/15 viewedAnaiuns approv• class ReindextargetStatsReportenptlvete const ste io .oT, Se mios - roces saneger-lock ;:peshace zessing senvronment = meiti:ouotcunc.consercnvtronsencscrtnosenvtronsencrvohsthis-senvsronment " senvironmentpublic function setUpdateTarget(string SupdateTarget): voidSthis->updateTarget = SupdateTarget:public function report(int SprocessedDocumentsCount): voidsthis->assertConfigured():Datadog:: increment(stats: 'jiminny.es-documents-synced',sanpleRate: 1.value: SprocessedDocumentsCount,SlockKey = sprintf(self::L0CK_KEY, Sthis-oupdateTaroet):1t/1 1snul1(Redisa.aet(SlockKew)))return;Redis::set(Slockkey, true);Redis::expire(SlockKey. self::L0CK_TTL_SECONDS):Sthis->reportMenoryUsage():private function assertConfiqured(): voidif (Sthis->updateTarget === null) ‹100% 142-• Thu 28 May 15:13:27nit review -O ∞) 0+95 sssse ~ Viewed...
|
85226
|
NULL
|
NULL
|
NULL
|
|
85227
|
2918
|
65
|
2026-05-28T12:13:20.753141+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970400753_m1.jpg...
|
PhpStorm
|
faVsco.js – Client.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
#12121 on JY-20963-fix-im Project: faVsco.js, menu
#12121 on JY-20963-fix-import-on-deleted-entity, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12121 on JY-20963-fix-import-on-deleted-entity, menu","depth":5,"on_screen":true,"help_text":"Pull request #12121 exists for current branch JY-20963-fix-import-on-deleted-entity","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-5714658179048184897
|
-8634297297851446848
|
visual_change
|
hybrid
|
NULL
|
Project: faVsco.js, menu
#12121 on JY-20963-fix-im Project: faVsco.js, menu
#12121 on JY-20963-fix-import-on-deleted-entity, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
PhpStormFileEditViewNavigateCodeRefactorRunToolsGitWindowHelpec2-user@ip-10-30-129-190:~ffmpeg0 X4lahlA100% CThu 28 May 15:13:20181ec2-user@ip-10-30-140-...₴7DOCKER#_####_#####\\###||\#/881DEV (-zsh)O [EMAIL] Linux 2023 (ECS Optimized)_m/For documentation, visit [URL_WITH_CREDENTIALS] ~]$ exitlogoutConnection to jiminny-prod-ecsi closed.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ applukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ vprodWarning: Permanently added 'jiminny-prod-ecs1' (ED25519) to the list of known hosts.A newer release of "Amazon Linux" is available.Version 2023.10.20260330:Version 2023.11.20260406:Version 2023.11.20260413:Version2023.11.20260427:Version2023.11.20260505:Version 2023.11.20260509:Version 2023.11.20260511:Version 2023.11.20260514:Run "/usr/bin/dnf check-release-update" for full release and version update info#_~\ ####_\ #####\\###1\#/Amazon Linux 2023 (ECS Optimized)/m/'For documentation, visit [URL_WITH_CREDENTIALS] ~]$ client_loop: send disconnect: Broken pipeukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-relay) $I...
|
85225
|
NULL
|
NULL
|
NULL
|
|
85225
|
2918
|
64
|
2026-05-28T12:13:18.842111+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970398842_m1.jpg...
|
PhpStorm
|
faVsco.js – Client.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
PhpStormFileEditViewNavigateCodeRefactorRunToolsGi PhpStormFileEditViewNavigateCodeRefactorRunToolsGit881DEV (-zsh)O 82-zshN3WindowHelpec2-user@ip-10-30-129-190:~ffmpeg€ 84DOCKER#_####_#####\\###||\#/V~'-zshlahlA100% (C47Thu 28 May 15:13:18181X5ec2-user@ip-10-30-129-...ec2-user@ip-10-30-140-...₴7Amazon Linux 2023 (ECSArtisanCLP Artisan_/m/Currency SymbolsFor documentation, visit [URL_WITH_CREDENTIALS] ~]$ exitlogoutConnection to jiminny-prod-ecs1 closed.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $lukas@Lukas-Kovaliks-MacBook-Pro-JiminnyWarning: Permanently added 'jiminny-prod-ecs:DatabasedatetimesFE logsGeneraljiminny debugMac symbolsPhpstormA newer release of "Amazon Linux" is availabPhpstorm classesVersion 2023.10.20260330:Version 2023.11.20260406:postman payloadsVersion 2023.11.20260413:Version2023.11.20260427:terminalVersion2023.11.20260505:User dataVersion2023.11.20260509:add field to sidekickVersion 2023.11.20260511:Version 2023.11.20260514:Run "/usr/bin/dnf check-release-update" for full release and version update info#_####_\ #####\\###1\#/Amazon Linux 2023 (ECS Optimized)₴82₴83₴4₴85286₴87288₴89View snippets for 'Artisan'Type to filter collections and snippets/m/'For documentation, visit [URL_WITH_CREDENTIALS] ~]$ client_loop: send disconnect: Broken pipeukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-relay) $I...
|
NULL
|
-3440525658930420579
|
NULL
|
click
|
ocr
|
NULL
|
PhpStormFileEditViewNavigateCodeRefactorRunToolsGi PhpStormFileEditViewNavigateCodeRefactorRunToolsGit881DEV (-zsh)O 82-zshN3WindowHelpec2-user@ip-10-30-129-190:~ffmpeg€ 84DOCKER#_####_#####\\###||\#/V~'-zshlahlA100% (C47Thu 28 May 15:13:18181X5ec2-user@ip-10-30-129-...ec2-user@ip-10-30-140-...₴7Amazon Linux 2023 (ECSArtisanCLP Artisan_/m/Currency SymbolsFor documentation, visit [URL_WITH_CREDENTIALS] ~]$ exitlogoutConnection to jiminny-prod-ecs1 closed.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $lukas@Lukas-Kovaliks-MacBook-Pro-JiminnyWarning: Permanently added 'jiminny-prod-ecs:DatabasedatetimesFE logsGeneraljiminny debugMac symbolsPhpstormA newer release of "Amazon Linux" is availabPhpstorm classesVersion 2023.10.20260330:Version 2023.11.20260406:postman payloadsVersion 2023.11.20260413:Version2023.11.20260427:terminalVersion2023.11.20260505:User dataVersion2023.11.20260509:add field to sidekickVersion 2023.11.20260511:Version 2023.11.20260514:Run "/usr/bin/dnf check-release-update" for full release and version update info#_####_\ #####\\###1\#/Amazon Linux 2023 (ECS Optimized)₴82₴83₴4₴85286₴87288₴89View snippets for 'Artisan'Type to filter collections and snippets/m/'For documentation, visit [URL_WITH_CREDENTIALS] ~]$ client_loop: send disconnect: Broken pipeukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-relay) $I...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85226
|
2919
|
70
|
2026-05-28T12:13:18.737215+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970398737_m2.jpg...
|
PhpStorm
|
faVsco.js – Client.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
FV faVsco.is ~#12121 on JY-20963-fx-inProinet vnhe FV faVsco.is ~#12121 on JY-20963-fx-inProinet vnhe heloers phi©ActivityControlier.php© VoiceConsentPrefix.phpNotificationsnObservers© AccountObserver.phpCyActwwooserver.pnp© ContactObserver.phgGroupObserver.pho© LeadObserver.phoC ProfileObserver.phpC SocialAccountObserver.phg© UserObserver.pho© UserRoleObserver.phc(in Policie:uProviderC Queuea Reoositonea RulesaServicesDa ActivityAiReodrlealendarIiconnerimermobiacte@ DecorateActivityDummym Helnarsv D Hubspor(i) AccountSyncStrategyIhctiontMcontctSwnestrateon• D DTO> FieldsThtauendOLekоkyseiwico.on© Kernel.phgMWiaKorCass wochexeR82* Breturn T The result of the APi callprivate function executeRequest(callable SapiCall)Opportunivsvncstratcov- Pac nation- Prosoec-SearchStrateoScacheKey = Sthis->getRateLimitCacheKeyOScacheotxozresac = keozst.oet scachekey)*if (is_string(ScachedExpiresAt) && is_numeric(ScachedExpiresAt)) 1Sremaining = naxl vax(cint)) ScachedExpiresAt - tineon:hrow new kacetinzcexceoezonsrenaining,neruonSantwaittecarch ethronadteoi4 (Sthiso>isHubsootRateLinit(Se))merryAttenthisorrarse?erny.ter e// NX: only the first job to receive a 429 in this burst sets the key.// Subsequent 42%s in the same burst leave the TTL untouched so theIl window is not reset by every concurrent job hitting the linit.Redis::set(ScacheKey, (string) (tine() + SretryAfter).Sthis->log->warning( Hubspot) Received 429 from API'.iteanSdl'configid'= Sthis->config->getido.as Scetryatter-ENAeMAONNAT→- Redisthrow new RateLinitException message: "Hubspot returned 429'. SretryAfter, Se):Service traits• UtilsThrow Sen- Wechookc) Batchsunceo ector cho© BatchSvncRedsService.oCleantono@ GiosedDealStaapsSeniceclnaalise rccarica onoprivate function getRateLinitCachekey@: strino...100% L74oo Inu co moy lo:lo.+0.Setm onwatoes noeslA console (STAGING)D6.00€ANo a-created at> DAT: SUBCMONOL "INTERVAL XA DAYITGROUP BY v.id, v.email, u.nane, u.softphone_numberORDER RY sns count783704FREREДI714-215716select + Eron teans whenp dm15C3IEACONCAT(u.id, CASE WHEN u.id = t.ouner_id THEN " (ouner)' ELSE "* END) AS user_id,t.ouner id FROM social accounts saJOIN users u on u.id = sa.sociable ic1.n<->1: on t.id = u.team_idd console (PROD) x C Service.php# console fiaumDojminnyv0458185Y0 ACacaado CodoxoKick of a new oroiset. Make chunosIMY"E729E732- 735* JOIN activities a ON fd.activity_id = a.1dWHERE activity_id = 79933459• AND f.crn_provider_id = 'hs_activity_type';id = 1 and id IN ((18688. 13934. 7160):Sid = 7168 order by id desc Linit 10:PARAtT GAAR MANGURAANOselect * fron teans where id = 1117select * fron activity searches where user_1d = 31054:Pohettendactivity search_filters where actlivity_search_id TN (88882. 88992)c. Fix Texikelay service TesteC Multi-Picklist Layout DisplaNtietnheetdor10o Podeswiett...
|
NULL
|
865779409316485795
|
NULL
|
click
|
ocr
|
NULL
|
FV faVsco.is ~#12121 on JY-20963-fx-inProinet vnhe FV faVsco.is ~#12121 on JY-20963-fx-inProinet vnhe heloers phi©ActivityControlier.php© VoiceConsentPrefix.phpNotificationsnObservers© AccountObserver.phpCyActwwooserver.pnp© ContactObserver.phgGroupObserver.pho© LeadObserver.phoC ProfileObserver.phpC SocialAccountObserver.phg© UserObserver.pho© UserRoleObserver.phc(in Policie:uProviderC Queuea Reoositonea RulesaServicesDa ActivityAiReodrlealendarIiconnerimermobiacte@ DecorateActivityDummym Helnarsv D Hubspor(i) AccountSyncStrategyIhctiontMcontctSwnestrateon• D DTO> FieldsThtauendOLekоkyseiwico.on© Kernel.phgMWiaKorCass wochexeR82* Breturn T The result of the APi callprivate function executeRequest(callable SapiCall)Opportunivsvncstratcov- Pac nation- Prosoec-SearchStrateoScacheKey = Sthis->getRateLimitCacheKeyOScacheotxozresac = keozst.oet scachekey)*if (is_string(ScachedExpiresAt) && is_numeric(ScachedExpiresAt)) 1Sremaining = naxl vax(cint)) ScachedExpiresAt - tineon:hrow new kacetinzcexceoezonsrenaining,neruonSantwaittecarch ethronadteoi4 (Sthiso>isHubsootRateLinit(Se))merryAttenthisorrarse?erny.ter e// NX: only the first job to receive a 429 in this burst sets the key.// Subsequent 42%s in the same burst leave the TTL untouched so theIl window is not reset by every concurrent job hitting the linit.Redis::set(ScacheKey, (string) (tine() + SretryAfter).Sthis->log->warning( Hubspot) Received 429 from API'.iteanSdl'configid'= Sthis->config->getido.as Scetryatter-ENAeMAONNAT→- Redisthrow new RateLinitException message: "Hubspot returned 429'. SretryAfter, Se):Service traits• UtilsThrow Sen- Wechookc) Batchsunceo ector cho© BatchSvncRedsService.oCleantono@ GiosedDealStaapsSeniceclnaalise rccarica onoprivate function getRateLinitCachekey@: strino...100% L74oo Inu co moy lo:lo.+0.Setm onwatoes noeslA console (STAGING)D6.00€ANo a-created at> DAT: SUBCMONOL "INTERVAL XA DAYITGROUP BY v.id, v.email, u.nane, u.softphone_numberORDER RY sns count783704FREREДI714-215716select + Eron teans whenp dm15C3IEACONCAT(u.id, CASE WHEN u.id = t.ouner_id THEN " (ouner)' ELSE "* END) AS user_id,t.ouner id FROM social accounts saJOIN users u on u.id = sa.sociable ic1.n<->1: on t.id = u.team_idd console (PROD) x C Service.php# console fiaumDojminnyv0458185Y0 ACacaado CodoxoKick of a new oroiset. Make chunosIMY"E729E732- 735* JOIN activities a ON fd.activity_id = a.1dWHERE activity_id = 79933459• AND f.crn_provider_id = 'hs_activity_type';id = 1 and id IN ((18688. 13934. 7160):Sid = 7168 order by id desc Linit 10:PARAtT GAAR MANGURAANOselect * fron teans where id = 1117select * fron activity searches where user_1d = 31054:Pohettendactivity search_filters where actlivity_search_id TN (88882. 88992)c. Fix Texikelay service TesteC Multi-Picklist Layout DisplaNtietnheetdor10o Podeswiett...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85224
|
2919
|
69
|
2026-05-28T12:13:13.566320+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970393566_m2.jpg...
|
PhpStorm
|
faVsco.js – Client.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
#12121 on JY-20963-fix-im Project: faVsco.js, menu
#12121 on JY-20963-fix-import-on-deleted-entity, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12121 on JY-20963-fix-import-on-deleted-entity, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.11569149,"height":0.025538707},"on_screen":true,"help_text":"Pull request #12121 exists for current branch JY-20963-fix-import-on-deleted-entity","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8374335,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"bounds":{"left":0.85272604,"top":0.019952115,"width":0.062832445,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-1678849104122188672
|
593894980799643872
|
visual_change
|
hybrid
|
NULL
|
Project: faVsco.js, menu
#12121 on JY-20963-fix-im Project: faVsco.js, menu
#12121 on JY-20963-fix-import-on-deleted-entity, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
rnpstomViewCoocWindowFV faVsco.s ~#12121 on JY-20963-fx-proidetwnapers.oh©ActivityControlier.php© VoiceConsentPrefix.phpNotificationsv Observers© AccountObserver.phcCActwwooserver.pnp© ContactObserver.phpGroupObserver.pho© LeadObserver.phoC ProfileObserver.phpC SocialAccountObserver.phg© UserObserver.pho© UserRoleObserver.phc> (i PoliciesuProvider• Queuea Reoositonea RulesaServicesActivityAiReodrleallendarleoseConnerimermobiacte@ DecorateActivityDummym Helnarsv D Hubspol(i) AccountSyncStrategyIhctiontMcontdSuncstrateon• D DTO› FieldsThtauendTNMAAAatOLenkоkyseiwico.on© Kernel.phpMWiaKorCass wochexebaseuoehraocathies wueswetheheatR8R* Breturn T The result of the APi callOpportunivsvncstratcov> Ma pacinationaProsoec SearchStrateoprivate function executeRequest(callable SapiCall)ScacheKey = Sthis->getRateLimitCacheKeyOScacheotxozresac = keozst.oet scachekey)if (is_string(ScachedExpiresAt) && is_numeric(ScachedExpiresAt)) 1Sremaining = naxl vax(cint)) ScachedExpiresAt - tineon:hrow new kacetinzcexceoezonsrenaining,neruonSantwaittecarch leinronabieoi4 (Sthiso>isHubsootRateLinit(Se))merry…ttenthisorrarse?erny.ter e// NX: only the first job to receive a 429 in this burst sets the key.// Subsequent 42%s in the same burst leave the TTL untouched so theIl window is not reset by every concurrent job hitting the linit.Redisoeset(Scachekey. (strino) (tine() e Sratevafter).lilunsnate Sunnont Sacades RedssSthis->log->warning( Hubspot) Received 429 from API'.iteanSdl'configid'=> Sthis->config-sgetido."retry after' => SretryAften=> Se->getMessageO→- Redisthrow new RateLinitException message: "Hubspot returned 429'. SretryAfter, Se):Service traits• UtilsThrow Sen- Wechookc) Batchsunceo ector cho© BatchSvncRedisService.oCileantono@ GiosedDealStadpsSeniceclnaalise rccarica onoprivate function getRateLinitCachekevO: strinol...;oo Inu co moy to:lo.TextRelayServiceTest+0.A SF fiminny@localhost)Á console (STAGING)D6.000ANo a-created at> DAT: SUBCMOWOL INTERVAL 3ODAYOIGROUP BY v.id, v.email, u.nane, u.softphone_numberORDER RY sns count783704ДЕДЕЦЕА-215716select * fron teans where id = 1SELECTCONCAT(u.1d, CASE WHEN u.id = t.ouner id THEN • ouner' ELSE ** END) AS user idsa.*t.ouner id FROM social accounts saconsole (PROD) x C Service.phpds consoe leu,Do jminny v8458185Y0 ACachado Codo XKick of a new oroisct. Make chunoeE732—73s— 734- 7357391I11MARAN A GAAR MAVE AOTONG WHAA AMAENA NE EROAOEO1Eselect * fron usersPARAtA GAAR MANGURAANOid IN ((18688. 13934. 7160):Sid = 7168 order by id desc Linit 10:select * fron teans where id = 1117select * fron activity searches where user_1d = 31954:Pohettendactivity search_filters where activity_search._id TN (88882. 88992)c. Fix Texikelay service TesteC Multi-Picklist Layout DisplaNtretnheet dor10"Pode swioth1 Wioderd Tesms 108:20 /5 charsl UTE-я*4 space...
|
85223
|
NULL
|
NULL
|
NULL
|
|
85223
|
2919
|
68
|
2026-05-28T12:13:07.239053+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970387239_m2.jpg...
|
PhpStorm
|
faVsco.js – Client.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
SIUCKVIChWindowHelpPwovscors#12121 on JY-20963-fol SIUCKVIChWindowHelpPwovscors#12121 on JY-20963-folProinet vO SAvice pinhe heloers phitpelereobiecistraiconSamiceTesuphr©ActivityControlier.php© VoiceConsentPrefix.phpNotificationsnObservers© AccountObserver.phpCyActwwooserver.pnp© ContactObserver.phpGroupObserver.pho© LeadObserver.phoC ProfileObserver.phpC SocialAccountObserver.phg© UserObserver.pho© UserRoleObserver.phc(in Policie:aProviders• Queuea Reoositonea RulesaServicesActivitylealendarI Conferenceimh Rullhomen CopperMmermobiacte@ DecorateActivityDummyHelpers@ Hubspo(i) AccountSyncStrategyMAetioneMcontndSuncstrateon• D DTO› FieldsOLeAkоkyscrco.on© UsersHistory.phpС) Team.prpOneindi.onoC TextRelayServiceTest.phgMWiaKorE .env.localcass woeh excnos daseuoehraolcathis nuesconcelehehearOpportunivsvncstratcov- Pac nation-ProsoecSearchStratco→- RedisService traits• UtilsWechookc) Batchsunceo ector cho© BatchSvncRedisService.ofCleantonoCLeAAA Den CTadAcCenoe* Srecurn n the result of the Apicoulonivate function execurerequest cal aole saosvaitaiScacheKey = Sthis->getRateLinitcacheKeyO:ScachedExpiresAt = Redis::get(ScacheKey)if is_string(ScachedExpiresAt) dd is_nuneric(ScachedExpiresat))Srenaining = max( value: 1,:Gint) ScachedExpiresAt - timeOD:throw new RateLimitExceptiondmessage: "Hubspot rate Linit (cached circuit-breaker)'.tryrecurn sapzealle} catch (Throwable Se) $aanses shuoscorkare btI/ NX: only the firstlCwlansours seesne keyuoseouen 4snbunst. leave the TTl untouched so the1 wandow is not reset byrrent job hitting the limit.Redhis:iserScachekey.stoing careo + Scetry.fter)lstions: "EX" SretevAfter. "Nx")Sthis->100->warning('(Hubsoot] Recefved 429 fron APT". [contasd=> Sthis->config->get.dO.= Seosaetwesehaeiouthoow now Catolsetycontoolt mattior "Wnhennt notuinnod Wol Chotnultton Col:throw Seclnaalise rccarica ono118private function getRateLinitCacheKey: stringi...=custom.logA console (STAGING)-782703704785785789=718711-717722725727729—730737— 738—7491IIITX: AUTONAND a.created_at › DATE_:GROUP BY u.id, u.email,ORDER BY sns_count DESC;select + Eron teans, wherlselect + Eron coles,SELECTCONCATU.Id, CASE WHsa.*t.ouner id FROM sociJOIN users u on u.id = sJOIN teans tWHERE u.tean_id = 1117 aSELECT * FROM actávitioSELECT * FROM actávitioSELECT * FROM crn configSELECT # FROM teans WHERselleetron usens whenselect * fron playbooksseleetron miawhonkeselect * fron playbook_ctseleet ron eoeselect * fron crn_field.SELECT * FROM crn_field_AOTM con Brelds 4 0M 4• JOIN activities a ON $NHERF Actvity "d = 7002ANn & con nrovsden 3alSELECT * FROM activity.mselect * fron text relayselect * fron activitiesselect * fron users whenPARAtT GAAR MANGUREANOselect & fron teans wherHoeActivity• Thu 28 May 15:13:06JiminnY …# backend# buescontusion-dinig# donut_timeengineerne# general# hapoy birthdavA infocoe intemal all# infra-chansed# infrastructure de#bu-team-infoiliminnv-bo# platform-team# platform-ticketstoroduct launche# random# released# suppor# thank-youssie the neoole of fimill6? Direct message.. Stefka Stoyanova1a llivana Netsevachuan omauPetko KashinskiGola Nimitrous: Todor Stamatol1 Stelivan Georsie.&r MireNikolav Vanko&. James GrahamLukas Kovalk y#:AppsS lin Gloud@ Describe what you are looking forVasil VasilevAdd canvas7 File2. Supervisor Shutdown Deadlock: In reapChildren®, callins pontl_waitpiilooayt the WNOHANG flag makes it a blockine call. If one child process gets stuck (c.g.waiting on a network timeout), the parent supervisor will freeze indehnitely and completely ignore your 10-second graceful shutdown lozic. (edited)3. Non-Atomic Redis Locks: The new ReindexTargetStatsReporter checks the lock with get and then creates it with set . Because the workers are truly parallel, they carboth read null at the exact same microsecond and both push duplicate metrics to Datados. This needs to be a sinale, atomic command (e.?. set with NX)).Vasil Vasilev 2:56 PM1 е добър коментарe intentonaККСНО ФлеелкОлИЕКОФИИИ ОИІКЕЛКУС ОНОК-ФТЬКОТУ-ЕЛТЬе ВОТАБОЖЕ БУЙ ССОХСТАХ ГОНОЯ МОНОМНИ ТОДОВИ АЙТСЯТЛУСЬНІ СЛЕ-ОЛФОНИМИКЯ СЕОХОЛЕLukas Kovalik 3.07 PMза трстата точка обаче наистина ли няма польожк!аз май си ги ползвам някьдеили е друг driverVasil Vasilev 3:10 PMне става, бях го направил така, и се счупиtkac Kowaiik 2utniomами и при мен се чумешеVasil Vasilev 3:11 PMoredrs nonnsoжa setSkoy, Svalue.lIinx = tmie. ex =0.0))Connrodis he craReLukas Kovalik 3:11 pNтака май не работеше Sresult = Redis-set(StestKey, StestValue, 'SX. StI. "NX"): а така ла Sresult = Redisuset(StestKey StestValue I'nx' 'ex' => Stll)Vasil Vasiley 3411 PvLukas Kovalik 3:12 PMне помня вечіVasil Vasilev 3:12 PMобратното може да сtkse Kowsll4 242.o1/може и да бръкамVacl Vacllev 2.12 pvRkOna uMаSlockAcquired - Redis::set(self::POLLING_LOCK.KEY, ison_encode(SlockDota), "EX", self::LOCK_TTL_SECONDS, "NX")ЗНАчИ ПЬОКОТО ЗЛБОТИMessage Vasil Vasiler...
|
NULL
|
1553543457553793673
|
NULL
|
click
|
ocr
|
NULL
|
SIUCKVIChWindowHelpPwovscors#12121 on JY-20963-fol SIUCKVIChWindowHelpPwovscors#12121 on JY-20963-folProinet vO SAvice pinhe heloers phitpelereobiecistraiconSamiceTesuphr©ActivityControlier.php© VoiceConsentPrefix.phpNotificationsnObservers© AccountObserver.phpCyActwwooserver.pnp© ContactObserver.phpGroupObserver.pho© LeadObserver.phoC ProfileObserver.phpC SocialAccountObserver.phg© UserObserver.pho© UserRoleObserver.phc(in Policie:aProviders• Queuea Reoositonea RulesaServicesActivitylealendarI Conferenceimh Rullhomen CopperMmermobiacte@ DecorateActivityDummyHelpers@ Hubspo(i) AccountSyncStrategyMAetioneMcontndSuncstrateon• D DTO› FieldsOLeAkоkyscrco.on© UsersHistory.phpС) Team.prpOneindi.onoC TextRelayServiceTest.phgMWiaKorE .env.localcass woeh excnos daseuoehraolcathis nuesconcelehehearOpportunivsvncstratcov- Pac nation-ProsoecSearchStratco→- RedisService traits• UtilsWechookc) Batchsunceo ector cho© BatchSvncRedisService.ofCleantonoCLeAAA Den CTadAcCenoe* Srecurn n the result of the Apicoulonivate function execurerequest cal aole saosvaitaiScacheKey = Sthis->getRateLinitcacheKeyO:ScachedExpiresAt = Redis::get(ScacheKey)if is_string(ScachedExpiresAt) dd is_nuneric(ScachedExpiresat))Srenaining = max( value: 1,:Gint) ScachedExpiresAt - timeOD:throw new RateLimitExceptiondmessage: "Hubspot rate Linit (cached circuit-breaker)'.tryrecurn sapzealle} catch (Throwable Se) $aanses shuoscorkare btI/ NX: only the firstlCwlansours seesne keyuoseouen 4snbunst. leave the TTl untouched so the1 wandow is not reset byrrent job hitting the limit.Redhis:iserScachekey.stoing careo + Scetry.fter)lstions: "EX" SretevAfter. "Nx")Sthis->100->warning('(Hubsoot] Recefved 429 fron APT". [contasd=> Sthis->config->get.dO.= Seosaetwesehaeiouthoow now Catolsetycontoolt mattior "Wnhennt notuinnod Wol Chotnultton Col:throw Seclnaalise rccarica ono118private function getRateLinitCacheKey: stringi...=custom.logA console (STAGING)-782703704785785789=718711-717722725727729—730737— 738—7491IIITX: AUTONAND a.created_at › DATE_:GROUP BY u.id, u.email,ORDER BY sns_count DESC;select + Eron teans, wherlselect + Eron coles,SELECTCONCATU.Id, CASE WHsa.*t.ouner id FROM sociJOIN users u on u.id = sJOIN teans tWHERE u.tean_id = 1117 aSELECT * FROM actávitioSELECT * FROM actávitioSELECT * FROM crn configSELECT # FROM teans WHERselleetron usens whenselect * fron playbooksseleetron miawhonkeselect * fron playbook_ctseleet ron eoeselect * fron crn_field.SELECT * FROM crn_field_AOTM con Brelds 4 0M 4• JOIN activities a ON $NHERF Actvity "d = 7002ANn & con nrovsden 3alSELECT * FROM activity.mselect * fron text relayselect * fron activitiesselect * fron users whenPARAtT GAAR MANGUREANOselect & fron teans wherHoeActivity• Thu 28 May 15:13:06JiminnY …# backend# buescontusion-dinig# donut_timeengineerne# general# hapoy birthdavA infocoe intemal all# infra-chansed# infrastructure de#bu-team-infoiliminnv-bo# platform-team# platform-ticketstoroduct launche# random# released# suppor# thank-youssie the neoole of fimill6? Direct message.. Stefka Stoyanova1a llivana Netsevachuan omauPetko KashinskiGola Nimitrous: Todor Stamatol1 Stelivan Georsie.&r MireNikolav Vanko&. James GrahamLukas Kovalk y#:AppsS lin Gloud@ Describe what you are looking forVasil VasilevAdd canvas7 File2. Supervisor Shutdown Deadlock: In reapChildren®, callins pontl_waitpiilooayt the WNOHANG flag makes it a blockine call. If one child process gets stuck (c.g.waiting on a network timeout), the parent supervisor will freeze indehnitely and completely ignore your 10-second graceful shutdown lozic. (edited)3. Non-Atomic Redis Locks: The new ReindexTargetStatsReporter checks the lock with get and then creates it with set . Because the workers are truly parallel, they carboth read null at the exact same microsecond and both push duplicate metrics to Datados. This needs to be a sinale, atomic command (e.?. set with NX)).Vasil Vasilev 2:56 PM1 е добър коментарe intentonaККСНО ФлеелкОлИЕКОФИИИ ОИІКЕЛКУС ОНОК-ФТЬКОТУ-ЕЛТЬе ВОТАБОЖЕ БУЙ ССОХСТАХ ГОНОЯ МОНОМНИ ТОДОВИ АЙТСЯТЛУСЬНІ СЛЕ-ОЛФОНИМИКЯ СЕОХОЛЕLukas Kovalik 3.07 PMза трстата точка обаче наистина ли няма польожк!аз май си ги ползвам някьдеили е друг driverVasil Vasilev 3:10 PMне става, бях го направил така, и се счупиtkac Kowaiik 2utniomами и при мен се чумешеVasil Vasilev 3:11 PMoredrs nonnsoжa setSkoy, Svalue.lIinx = tmie. ex =0.0))Connrodis he craReLukas Kovalik 3:11 pNтака май не работеше Sresult = Redis-set(StestKey, StestValue, 'SX. StI. "NX"): а така ла Sresult = Redisuset(StestKey StestValue I'nx' 'ex' => Stll)Vasil Vasiley 3411 PvLukas Kovalik 3:12 PMне помня вечіVasil Vasilev 3:12 PMобратното може да сtkse Kowsll4 242.o1/може и да бръкамVacl Vacllev 2.12 pvRkOna uMаSlockAcquired - Redis::set(self::POLLING_LOCK.KEY, ison_encode(SlockDota), "EX", self::LOCK_TTL_SECONDS, "NX")ЗНАчИ ПЬОКОТО ЗЛБОТИMessage Vasil Vasiler...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85222
|
2918
|
63
|
2026-05-28T12:13:07.133958+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970387133_m1.jpg...
|
iTerm2
|
NULL
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
FirefoxFileEditViewHistoryBookmarksProfilesToolsWi FirefoxFileEditViewHistoryBookmarksProfilesToolsWindowHelpec2-user@ip-10-30-129-190:~screenpipe"O &4‹$0(ah]A100% <78• Thu 28 May 15:13:06181ec2-user@ip-10-30-140-...₴7DOCKER#_####_#####\\###||\#/V~'881DEV (-zsh)O [EMAIL] Linux 2023 (ECS Optimized)_/m/For documentation, visit [URL_WITH_CREDENTIALS] ~]$ exitlogoutConnection to jiminny-prod-ecsi closed.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ applukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ vprodWarning: Permanently added 'jiminny-prod-ecs1' (ED25519) to the list of known hosts.A newer release of "Amazon Linux" is available.Version 2023.10.20260330:Version 2023.11.20260406:Version 2023.11.20260413:Version2023.11.20260427:Version2023.11.20260505:Version 2023.11.20260509:Version 2023.11.20260511:Version 2023.11.20260514:Run "/usr/bin/dnf check-release-update" for full release and version update info#_~\ ####_\ #####\\###1\#/Amazon Linux 2023 (ECS Optimized)/m/'For documentation, visit [URL_WITH_CREDENTIALS] ~]$ client_loop: send disconnect: Broken pipeukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-relay) $I...
|
NULL
|
2148585495112874450
|
NULL
|
click
|
ocr
|
NULL
|
FirefoxFileEditViewHistoryBookmarksProfilesToolsWi FirefoxFileEditViewHistoryBookmarksProfilesToolsWindowHelpec2-user@ip-10-30-129-190:~screenpipe"O &4‹$0(ah]A100% <78• Thu 28 May 15:13:06181ec2-user@ip-10-30-140-...₴7DOCKER#_####_#####\\###||\#/V~'881DEV (-zsh)O [EMAIL] Linux 2023 (ECS Optimized)_/m/For documentation, visit [URL_WITH_CREDENTIALS] ~]$ exitlogoutConnection to jiminny-prod-ecsi closed.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ applukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ vprodWarning: Permanently added 'jiminny-prod-ecs1' (ED25519) to the list of known hosts.A newer release of "Amazon Linux" is available.Version 2023.10.20260330:Version 2023.11.20260406:Version 2023.11.20260413:Version2023.11.20260427:Version2023.11.20260505:Version 2023.11.20260509:Version 2023.11.20260511:Version 2023.11.20260514:Run "/usr/bin/dnf check-release-update" for full release and version update info#_~\ ####_\ #####\\###1\#/Amazon Linux 2023 (ECS Optimized)/m/'For documentation, visit [URL_WITH_CREDENTIALS] ~]$ client_loop: send disconnect: Broken pipeukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-relay) $I...
|
85219
|
NULL
|
NULL
|
NULL
|
|
85221
|
2919
|
67
|
2026-05-28T12:13:00.117238+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970380117_m2.jpg...
|
Slack
|
Vasil Vasilev (DM) - Jiminny Inc - 2 new items - S Vasil Vasilev (DM) - Jiminny Inc - 2 new items - Slack...
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Lukas Kovalik
Today at 11:55:58 AM
11:55 AM
здрасти Васко, може ли един approve
https://github.com/jiminny/app/pull/12136
https://github.com/jiminny/app/pull/12136
Vasil Vasilev
Today at 12:00:25 PM
12:00 PM
Здрасти, Лукаш...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"bounds":{"left":0.5056516,"top":0.058260176,"width":0.011968086,"height":0.028731046},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"bounds":{"left":0.50299203,"top":0.10055866,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"bounds":{"left":0.50664896,"top":0.13806863,"width":0.009973404,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"bounds":{"left":0.50299203,"top":0.15482841,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":8,"bounds":{"left":0.50764626,"top":0.19233839,"width":0.007978723,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":6,"bounds":{"left":0.50299203,"top":0.20909816,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":8,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.012965426,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.0026595744,"height":0.011173184}},{"char_start":1,"char_count":7,"bounds":{"left":0.50764626,"top":0.24660814,"width":0.010638298,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":6,"bounds":{"left":0.50299203,"top":0.26336792,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":8,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0076462766,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5099734,"top":0.3008779,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Later","depth":6,"bounds":{"left":0.50299203,"top":0.31763768,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Later","depth":8,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.008643617,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5093085,"top":0.35514766,"width":0.0066489363,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"More…","depth":6,"bounds":{"left":0.50299203,"top":0.3719074,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"More","depth":8,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.008976064,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.0033244682,"height":0.011173184}},{"char_start":1,"char_count":3,"bounds":{"left":0.5106383,"top":0.4094174,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXStaticText","text":"Unreads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Threads","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Huddles","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Drafts & sent","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Directories","depth":13,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-backend-engineers","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"platform-inner-team","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ai-chapter","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"alerts","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"backend","depth":15,"bounds":{"left":0.5422208,"top":0.09736632,"width":0.018284574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.09736632,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54521275,"top":0.09736632,"width":0.015292553,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"bugs","depth":15,"bounds":{"left":0.5422208,"top":0.11971269,"width":0.010638298,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.11971269,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":3,"bounds":{"left":0.54521275,"top":0.11971269,"width":0.00731383,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"confusion-clinic","depth":15,"bounds":{"left":0.5422208,"top":0.14205906,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.14205906,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54454786,"top":0.14205906,"width":0.032247342,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"donut_time","depth":15,"bounds":{"left":0.5422208,"top":0.16440542,"width":0.025265958,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.16440542,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54521275,"top":0.16440542,"width":0.022273935,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"engineering","depth":15,"bounds":{"left":0.5422208,"top":0.1867518,"width":0.025930852,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.1867518,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":10,"bounds":{"left":0.54488033,"top":0.1867518,"width":0.022938829,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"general","depth":15,"bounds":{"left":0.5422208,"top":0.20909816,"width":0.016289894,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.20909816,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54488033,"top":0.20909816,"width":0.013297873,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"happy_birthday","depth":15,"bounds":{"left":0.5422208,"top":0.23144454,"width":0.033909574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.23144454,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.54521275,"top":0.23144454,"width":0.030917553,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infosec_internal_all","depth":15,"bounds":{"left":0.5422208,"top":0.25379092,"width":0.041888297,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.25379092,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":19,"bounds":{"left":0.54355055,"top":0.25379092,"width":0.040226065,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infra-changes","depth":15,"bounds":{"left":0.5422208,"top":0.27613726,"width":0.029587766,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.27613726,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54355055,"top":0.27613726,"width":0.02825798,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infrastructure_dev","depth":15,"bounds":{"left":0.5422208,"top":0.29848364,"width":0.040226065,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.29848364,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":17,"bounds":{"left":0.54355055,"top":0.29848364,"width":0.038896278,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"jbu-team-info","depth":15,"bounds":{"left":0.5422208,"top":0.32083002,"width":0.029920213,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.32083002,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54355055,"top":0.32083002,"width":0.028590426,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"jiminny-bg","depth":15,"bounds":{"left":0.5422208,"top":0.34317636,"width":0.023271276,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.34317636,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54355055,"top":0.34317636,"width":0.021609042,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"platform-team","depth":15,"bounds":{"left":0.5422208,"top":0.36552274,"width":0.03158245,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.36552274,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54521275,"top":0.36552274,"width":0.028590426,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"platform-tickets","depth":15,"bounds":{"left":0.5422208,"top":0.38786912,"width":0.034906916,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.38786912,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54521275,"top":0.38786912,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"product_launches","depth":15,"bounds":{"left":0.5422208,"top":0.4102155,"width":0.03856383,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.4102155,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54521275,"top":0.4102155,"width":0.03557181,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"random","depth":15,"bounds":{"left":0.5422208,"top":0.43256184,"width":0.016954787,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.43256184,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":5,"bounds":{"left":0.54421544,"top":0.43256184,"width":0.014960106,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"releases","depth":15,"bounds":{"left":0.5422208,"top":0.45490822,"width":0.01761968,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.45490822,"width":0.0016622341,"height":0.014365523}},{"char_start":1,"char_count":7,"bounds":{"left":0.54388297,"top":0.45490822,"width":0.015957447,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"support","depth":15,"bounds":{"left":0.5422208,"top":0.4772546,"width":0.017287234,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.4772546,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54454786,"top":0.4772546,"width":0.01462766,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"thank-yous","depth":15,"bounds":{"left":0.5422208,"top":0.49960095,"width":0.024601065,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.49960095,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54421544,"top":0.49960095,"width":0.022606382,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"the_people_of_jiminny","depth":15,"bounds":{"left":0.5422208,"top":0.5219473,"width":0.045212764,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5219473,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":20,"bounds":{"left":0.54421544,"top":0.5219473,"width":0.04720745,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Vasil Vasilev","depth":15,"bounds":{"left":0.5422208,"top":0.5746209,"width":0.026595745,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5746209,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54521275,"top":0.5746209,"width":0.023271276,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Stefka Stoyanova","depth":15,"bounds":{"left":0.5422208,"top":0.5969673,"width":0.037898935,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5969673,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54488033,"top":0.5969673,"width":0.03523936,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Iliyana Netseva","depth":15,"bounds":{"left":0.5422208,"top":0.61931366,"width":0.03324468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.61931366,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54355055,"top":0.61931366,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Stoyan Tomov","depth":15,"bounds":{"left":0.5422208,"top":0.64166003,"width":0.030917553,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.64166003,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":11,"bounds":{"left":0.54488033,"top":0.64166003,"width":0.027925532,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Petko Kashinski","depth":15,"bounds":{"left":0.5422208,"top":0.6640064,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.6640064,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54521275,"top":0.6640064,"width":0.03158245,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Galya Dimitrova","depth":15,"bounds":{"left":0.5422208,"top":0.6863527,"width":0.03523936,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.6863527,"width":0.003656915,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54587764,"top":0.6863527,"width":0.03158245,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Todor Stamatov","depth":15,"bounds":{"left":0.5422208,"top":0.7086991,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7086991,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.54454786,"top":0.7086991,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Steliyan Georgiev","depth":15,"bounds":{"left":0.5422208,"top":0.7310455,"width":0.038231384,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7310455,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":16,"bounds":{"left":0.54488033,"top":0.7310455,"width":0.03557181,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Ves","depth":15,"bounds":{"left":0.5422208,"top":0.75339186,"width":0.007978723,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.75339186,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":2,"bounds":{"left":0.54521275,"top":0.75339186,"width":0.004986702,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Mira","depth":15,"bounds":{"left":0.5422208,"top":0.77573824,"width":0.010305851,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.77573824,"width":0.004654255,"height":0.014365523}},{"char_start":1,"char_count":3,"bounds":{"left":0.546875,"top":0.77573824,"width":0.005319149,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Nikolay Yankov","depth":15,"bounds":{"left":0.5422208,"top":0.7980846,"width":0.032912236,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7980846,"width":0.0039893617,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.5462101,"top":0.7980846,"width":0.028922873,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"James Graham","depth":15,"bounds":{"left":0.5422208,"top":0.820431,"width":0.031914894,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.820431,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":11,"bounds":{"left":0.54421544,"top":0.820431,"width":0.029920213,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Lukas Kovalik","depth":15,"bounds":{"left":0.5422208,"top":0.8427773,"width":0.029587766,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.8427773,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54488033,"top":0.8427773,"width":0.026928192,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"you","depth":15,"bounds":{"left":0.5744681,"top":0.8427773,"width":0.0063164895,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5744681,"top":0.8427773,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":2,"bounds":{"left":0.5767952,"top":0.8427773,"width":0.0056515955,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Jira Cloud","depth":15,"bounds":{"left":0.5422208,"top":0.8954509,"width":0.021941489,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.8954509,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54421544,"top":0.8954509,"width":0.019946808,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Toast","depth":15,"bounds":{"left":0.5422208,"top":0.91779727,"width":0.011635638,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.91779727,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":4,"bounds":{"left":0.54454786,"top":0.91779727,"width":0.00930851,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Google Calendar","depth":15,"bounds":{"left":0.5422208,"top":0.94014364,"width":0.030585106,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.94014364,"width":0.003656915,"height":0.014365523}},{"char_start":1,"char_count":14,"bounds":{"left":0.54587764,"top":0.94014364,"width":0.032912236,"height":0.014365523}}],"role_description":"text"},{"role":"AXRadioButton","text":"Messages","depth":9,"bounds":{"left":0.60206115,"top":0.09177973,"width":0.030917553,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Messages","depth":11,"bounds":{"left":0.61136967,"top":0.10055866,"width":0.018949468,"height":0.012769354},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.61136967,"top":0.10055866,"width":0.0039893617,"height":0.012769354}},{"char_start":1,"char_count":7,"bounds":{"left":0.61535907,"top":0.10055866,"width":0.014960106,"height":0.012769354}}],"role_description":"text"},{"role":"AXRadioButton","text":"Add canvas","depth":10,"bounds":{"left":0.63397604,"top":0.09177973,"width":0.034242023,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Add canvas","depth":12,"bounds":{"left":0.64328456,"top":0.10055866,"width":0.022273935,"height":0.012769354},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.64328456,"top":0.10055866,"width":0.0033244682,"height":0.012769354}},{"char_start":1,"char_count":9,"bounds":{"left":0.6462766,"top":0.10055866,"width":0.019281914,"height":0.012769354}}],"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":9,"bounds":{"left":0.66921544,"top":0.09177973,"width":0.020944148,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":11,"bounds":{"left":0.67852396,"top":0.10055866,"width":0.008976064,"height":0.012769354},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Pins","depth":9,"bounds":{"left":0.69148934,"top":0.09177973,"width":0.020279255,"height":0.030327214},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Pins","depth":11,"bounds":{"left":0.70079786,"top":0.10055866,"width":0.00831117,"height":0.012769354},"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Add and Edit Channel Tabs","depth":9,"bounds":{"left":0.71276593,"top":0.09177973,"width":0.010970744,"height":0.030327214},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Canvas","depth":9,"bounds":{"left":0.59640956,"top":0.0518755,"width":0.015957447,"height":0.0007980846},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"List","depth":9,"bounds":{"left":0.59640956,"top":0.0518755,"width":0.007978723,"height":0.0007980846},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Folder","depth":9,"bounds":{"left":0.59640956,"top":0.0518755,"width":0.013962766,"height":0.0007980846},"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Jump to date","depth":15,"bounds":{"left":0.7849069,"top":0.12689546,"width":0.025265958,"height":0.022346368},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Lukas Kovalik","depth":16,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 11:55:58 AM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"11:55 AM","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"здрасти Васко, може ли един approve","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"https://github.com/jiminny/app/pull/12136","depth":17,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"https://github.com/jiminny/app/pull/12136","depth":18,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Vasil Vasilev","depth":16,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Today at 12:00:25 PM","depth":16,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12:00 PM","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Здрасти, Лукаш","depth":17,"on_screen":false,"role_description":"text"}]...
|
-6752921888300212437
|
-8211830214848965010
|
visual_change
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
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_jiminny
Vasil Vasilev
Stefka Stoyanova
Iliyana Netseva
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Google Calendar
Messages
Messages
Add canvas
Add canvas
Files
Files
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Lukas Kovalik
Today at 11:55:58 AM
11:55 AM
здрасти Васко, може ли един approve
https://github.com/jiminny/app/pull/12136
https://github.com/jiminny/app/pull/12136
Vasil Vasilev
Today at 12:00:25 PM
12:00 PM
Здрасти, Лукаш
SIUCKVIChRotonWindowHelpPwovscors#12121 on JY-20963-folProinet vO SAvice pinhe heloers phitpelereobiecistraiconSamiceTesuphr©ActivityControlier.php© VoiceConsentPrefix.phpNotificationsv Observers© AccountObserver.phpCyActwwooserver.pnp© ContactObserver.phgGroupObserver.pho© LeadObserver.phoC ProfileObserver.phpC SocialAccountObserver.phg© UserObserver.pho© UserRoleObserver.phc> (i PoliciesaProviders• Queuea Reoositonea RulesaServicesActivityTeallendarI Conferenceimh Rullhomea CopperMmermobiacte@ DecorateActivityDummyHelpers@ Hubspo(i) AccountSyncStrategyMAetioneMcontndSuncstrateon• D DTO› FieldsOLeAkоkyscrco.on© UsersHistory.phpС) Team.prpOneindi.onoC TextRelayServiceTest.phgMWiaKorE .env.localcass woeh exenos baseuoehrdo cathit wusowe theheaOpportunivsvncstratcov- Pac nation-ProsoecSearchStratco→- RedisService traits• UtilsWechookc) Batchsunceo ector cho© BatchSvncRedisService.ofCleantonoCLeAAA Den CTadAcCenoe* Creturn n the resul of the Apr cotlonivate function execurerequest(cal able saosraienScacheKey = Sthis->getRateLinitcacheKeyO:ScachedExpiresAt = Redis::get(ScacheKey)if (is_string(ScachedExpiresAt) && is_numeric(ScachedExpiresAt)) {Srenaining = max( value: 1,:Gint) ScachedExpiresAt - timeOD:throw new RateLimitExceptiondmessage: "Hubspot rate Linit (cached circuit-breaker)'.tryrecurn sapzealle} catch (Throwable Se) $aanses shuoscorkare btrerrviterEnsoso se emeimeeeI/ NX: only the firstlCwlannsours selesnekeywoseouen 4snindburst leave the TTL untouched so the1 wandow is not reset byrrent job hitting the limit.Redhis:iserScachekey.sting) careo + Scetcy.fter)stions: "EX" SretevAfter. "Nx")Sthis->100->warning('(Hubsoot] Recefved 429 fron APT". [contasd=> Sthis->config->get.dO.= Seosaetwesehaeiouthoom now Catolsetsycontoolt cattior "Hnhennt notunnod wot Chotnuniton Colthrow Seclnaalise rccarica ono118private function getRateLinitCacheKey: stringi...=custom.loglaravel.logA console [STAGING-78278578785786711713714-215-717TTIII722.722723725727729- 77—730737- 738)TX: AUTONAND a.created_at › DATE_:GROUP BY u.id, u.email,ORDER BY sne count DESMselect + Eron teans, wherlselect + Eron coles,CEIEOTCONCATU.Id, CASE WHsa.*t.ouner id FROM sociJOIN users u on u.id = sJOIN teans tWHERE u.tean_id = 1117 aSELECT * FROM actávitioSELECT * FROM actávitioSELECT * FROM crn configSELECT # FROM teans WHERselleetron usens whenselect * fron playbooksseleetron miawhonkeselect * fron playbook_ctseleet ron eoeselect * fron crn_field.vSELECT * FROM crn_field_AOTM con Brelds 4 0M 4• JOIN activities a ON $NHERF Actvity "d = 7002AND € con onovider saSELECT * FROM activity.mselect * fron text relayselect * fron activitiesselect * fron users whenMARAt GAAR NANRURAANePAlRetGhAn dAAAIRdAMselect & fron teans wherPohattoon activtysHoeDMsActivityMonJiminnY ….# backend# buescontusion-dinig# donut_time#enpineerine# generall# happy birthdavA infocoe intemal all# infra-chansed# infrastructure de#bu-team-infoiliminnv-bost olatform-team# platform-ticketstoroduct launche# random# releases# suppor# thank-youssie the neoole of fimill6? Direct message.Vasil VasilenF8. Stefka Stoyanova1a llivana NetsevaA Ctovan TomnulPetko KashinskiGola Nimitrous: Todor Stamatol1 Stelivan Georsie.&r MireNikolav Vanko&. James GrahamLukas KovalkyTO0У L7inu co moy tolcio@ Describe what you are looking forVasil Vasileve MessagerNeRdd canvu riies2. Supervisor Shutdown Deadlock: In recpChildrenO, calling pentl_waitpid without the WNOHANG flag, makes it a blocking, call. If one child process gets stuck (e.gwaiting on a network timeout), the parent supervisor will freeze indehnitely and completely ignore your 10-second graceful shutdown logic. (edited)3. Non-Atomic Redis Locks: The new ReindexTargetStatsReporter checks the lock with get and then creates it with set. Because the workers are truly parallel, they carboth read null at the exact same microsecond and both push duplicate metrics to Datadog. Uhis needs to be a single, atomic command (e.g.. set with Nx),Vasil Vasilev 2:56 PM1 е добър коментарetnenldonh3 сьцо e intentional порали факта, че phpredis driver-a не полльржа set ex +nx параметри, и трябва ла се пуснат лее операции set + expireLukas Kovalik 3.07 PMOKaso nwehaxnaxnor %eninза третата точка обаче наистина ли няма подьржкааз май си ги ползвам някьдеили е друг driverWcllvaclleu 2u0ovHA CHARALDOY CO HARMARUN TAKAU CA (MMONLukas Kovalik 3.10 pNами и пои мен сА чумашьVasil Vasiley 2.11 pwpredis поддьржа set(skey, >value. Lnx = true, ex =60)c phoredis не ставаLukas Kovalik 3:11 PMтака май не работеще Sresult = Redisuset(StestKey, StestValue 'EX. Sttl. "NX"): а така ла Sresult = Redisuset(StestKey, StestValue ('nx' 'ex' => Sttll):Vasil Vasilev 3:11 PMвторото пробвах, и не станаvar Kaush minorMAMAkAnTuAне помня вечоVasil Vasilev 3:12 PMобратното може да eLukas Kovalik 3:12 PMможе и ла блькамVasil Vasilev 3:12 PMSlockAcquired - Redis::set(self::POLLING_LOCK_KEY, Json_encode(SlockData), "EX", self::LOCK_TTL-SECONDS, *NX"):...
|
85220
|
NULL
|
NULL
|
NULL
|
|
85220
|
2919
|
66
|
2026-05-28T12:12:55.054305+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970375054_m2.jpg...
|
PhpStorm
|
faVsco.js – Client.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
rapstomEV favscojs ~ViewCooc#12121 on JY-20963-fix rapstomEV favscojs ~ViewCooc#12121 on JY-20963-fix-InWindow© VoiceConsentPrefix.phpNotificationsv Observers© AccountObserver.php© ActivityObserver.php© ContactObserver.php© [EMAIL]© ProfileObserver.php© SocialAccountObserver.phpUserObserver.phpUserRoleObserver.php> Co PoliciesaProvidersD Queuea ReoositoneE RulesaServicesActivityAiReodrleallendar@ BullhornCopper|mermobiacteDecorateActivityDummy› @ Helpers~ HubspotAccountSyncStrategyMAetione( ContactSyncStrategywnapers.ohOLekоkyseiwico.onOAeindi.oneMWiaKorCass wochexeR82* Ecetucn T The result of the API calzprivate function executeRequest(callable SapiCall)ScacheKey = $this->getRateLinitCacheKeyO:scacheotxozresac = keots.toet scachekey1f (18_8tring(ScachedExpiresAt) S& 1s_numeric(ScachedExpiresAt)) €Srenaznzno = max value(int) ScachedExpiresAt - time()):throw new RateLimitExceptionCmessage:Hubspot rare biazx cached carcuz-breaken"return SapiCallO:} catch (Throwable Se)fif (Sthis->isHubspotRateLinit(Se)) (Srerryaten"Thisornarse?erny.tTer e// NX: only the first job to receive a 429 in this burst sets the key.// Subsequent 429s in the sane burst leave the TTL untouched so theIl window is not reset by every concurrent job hitting the limit.Redis: :set(ScacheKey, (string) (tine() + SretryAfter),Sthis->log->warning(^[Hubspot] Received 429 fron API', [› Fields'team id'=> Sthis->config->tean id.# Journal'config_id'= Sthis->config->getIdO.Ea Metadata'retry_after' => SretryAfter,=> Se->getMessageo.Opportunivsvncstratcov- Pac nation-ProsoecSearchStratco→- Redisthrow new RateLinitException( message: 'Hubspot returned 429', SretryAfter, $e);Service traits• Utilsthrow Ser- Wechookc) Batchsunceo ector cho© BatchSyncRedisService.ptCleantono© ClosedDealStagesService.clnaalise rccarica onoprivate function getRateLimitCachekey(): stringf...o Inu co moy 1o:l2o4U TextRelayServiceTest~+0.A SF (iminny@localhost)console [PROD] x © Service.php# console fiaumA console [STAGING)D000€ANo a-created at> DAT: SUBCMONOL "INTERVAL XA DAYIGROUP BY u.id, v.enail, U.nane, u.softphone_numberORDER BY sns_count-782783704ВАДДЕВЕК715716FRRREE728729E732—73s-734-736737- 73568fminry~045 A1 441 X 66 Aselect * fron teans where id = 1;SELECTCONCAT(u.1d, CASE WHEN U.id = t.ouner_id THEN • (ouner)' ELSE "* END) AS user_id,sa.*,t.ouner_id FROM social_accounts saJOIN users u on u.id = sa.sociable_idJOIN teans t(1.n<->1: on t.id = u.tean_idWHERE u.tean_id = 1117 and sa.provider = 'hubspot":SELECT * FROM activities WHERE uuid_to_bin('8024fffb-2df7-4017-91f4-d9f896050248') = uuid; # 79933459 YESSELECT * FROM activitios WHERE Uuid_to_bin('[CREDIT_CARD]-927f-4f4da208185c*) = uuid; # 80186192 NOid = 5473;select * fron playbook_categories where id = 43783;lect * fron playbook_categories where playbook_id = 5473;select * fron crn_fields where id = 659242)crn_field_values where crn_field_ id = 659242SELECT * FROM crm_fleld_data fd* JOIN crn_fields fON fd.crm_field_id = f.id• JOIN activities a ON fd.activity_id = a.10WHERE activity_id = 79933459• AND f.crn_provider_id = 'hs_activity_type';select * fron text_relays where created_at > '2026-85-01':select * fron activities where user id IN (7168.select * fron users where team_id = 1 and id IN (18608, 13934, 7160);select * fron activities where user_id = 7160 order by id desc linit 10;select * fron teans where id = 1117;select x fron activity_searches where user_id = 31054;select + fronactivity_search_filters where activity_search_id IN (88882, 88902);Cachado Codo XoKick off a new project. Make changeseEnexthal Sanha yC Multi-Picklist Layout DisplaeClient.phpfL99-182"PodswiothW Wodtur Teams 10247 UTE-яensd....
|
NULL
|
5171856020865434183
|
NULL
|
click
|
ocr
|
NULL
|
rapstomEV favscojs ~ViewCooc#12121 on JY-20963-fix rapstomEV favscojs ~ViewCooc#12121 on JY-20963-fix-InWindow© VoiceConsentPrefix.phpNotificationsv Observers© AccountObserver.php© ActivityObserver.php© ContactObserver.php© [EMAIL]© ProfileObserver.php© SocialAccountObserver.phpUserObserver.phpUserRoleObserver.php> Co PoliciesaProvidersD Queuea ReoositoneE RulesaServicesActivityAiReodrleallendar@ BullhornCopper|mermobiacteDecorateActivityDummy› @ Helpers~ HubspotAccountSyncStrategyMAetione( ContactSyncStrategywnapers.ohOLekоkyseiwico.onOAeindi.oneMWiaKorCass wochexeR82* Ecetucn T The result of the API calzprivate function executeRequest(callable SapiCall)ScacheKey = $this->getRateLinitCacheKeyO:scacheotxozresac = keots.toet scachekey1f (18_8tring(ScachedExpiresAt) S& 1s_numeric(ScachedExpiresAt)) €Srenaznzno = max value(int) ScachedExpiresAt - time()):throw new RateLimitExceptionCmessage:Hubspot rare biazx cached carcuz-breaken"return SapiCallO:} catch (Throwable Se)fif (Sthis->isHubspotRateLinit(Se)) (Srerryaten"Thisornarse?erny.tTer e// NX: only the first job to receive a 429 in this burst sets the key.// Subsequent 429s in the sane burst leave the TTL untouched so theIl window is not reset by every concurrent job hitting the limit.Redis: :set(ScacheKey, (string) (tine() + SretryAfter),Sthis->log->warning(^[Hubspot] Received 429 fron API', [› Fields'team id'=> Sthis->config->tean id.# Journal'config_id'= Sthis->config->getIdO.Ea Metadata'retry_after' => SretryAfter,=> Se->getMessageo.Opportunivsvncstratcov- Pac nation-ProsoecSearchStratco→- Redisthrow new RateLinitException( message: 'Hubspot returned 429', SretryAfter, $e);Service traits• Utilsthrow Ser- Wechookc) Batchsunceo ector cho© BatchSyncRedisService.ptCleantono© ClosedDealStagesService.clnaalise rccarica onoprivate function getRateLimitCachekey(): stringf...o Inu co moy 1o:l2o4U TextRelayServiceTest~+0.A SF (iminny@localhost)console [PROD] x © Service.php# console fiaumA console [STAGING)D000€ANo a-created at> DAT: SUBCMONOL "INTERVAL XA DAYIGROUP BY u.id, v.enail, U.nane, u.softphone_numberORDER BY sns_count-782783704ВАДДЕВЕК715716FRRREE728729E732—73s-734-736737- 73568fminry~045 A1 441 X 66 Aselect * fron teans where id = 1;SELECTCONCAT(u.1d, CASE WHEN U.id = t.ouner_id THEN • (ouner)' ELSE "* END) AS user_id,sa.*,t.ouner_id FROM social_accounts saJOIN users u on u.id = sa.sociable_idJOIN teans t(1.n<->1: on t.id = u.tean_idWHERE u.tean_id = 1117 and sa.provider = 'hubspot":SELECT * FROM activities WHERE uuid_to_bin('8024fffb-2df7-4017-91f4-d9f896050248') = uuid; # 79933459 YESSELECT * FROM activitios WHERE Uuid_to_bin('[CREDIT_CARD]-927f-4f4da208185c*) = uuid; # 80186192 NOid = 5473;select * fron playbook_categories where id = 43783;lect * fron playbook_categories where playbook_id = 5473;select * fron crn_fields where id = 659242)crn_field_values where crn_field_ id = 659242SELECT * FROM crm_fleld_data fd* JOIN crn_fields fON fd.crm_field_id = f.id• JOIN activities a ON fd.activity_id = a.10WHERE activity_id = 79933459• AND f.crn_provider_id = 'hs_activity_type';select * fron text_relays where created_at > '2026-85-01':select * fron activities where user id IN (7168.select * fron users where team_id = 1 and id IN (18608, 13934, 7160);select * fron activities where user_id = 7160 order by id desc linit 10;select * fron teans where id = 1117;select x fron activity_searches where user_id = 31054;select + fronactivity_search_filters where activity_search_id IN (88882, 88902);Cachado Codo XoKick off a new project. Make changeseEnexthal Sanha yC Multi-Picklist Layout DisplaeClient.phpfL99-182"PodswiothW Wodtur Teams 10247 UTE-яensd....
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85219
|
2918
|
62
|
2026-05-28T12:12:54.950020+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970374950_m1.jpg...
|
PhpStorm
|
faVsco.js – Client.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
#12121 on JY-20963-fix-im Project: faVsco.js, menu
#12121 on JY-20963-fix-import-on-deleted-entity, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12121 on JY-20963-fix-import-on-deleted-entity, menu","depth":5,"on_screen":true,"help_text":"Pull request #12121 exists for current branch JY-20963-fix-import-on-deleted-entity","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-5491484594888514086
|
-7050964252790406720
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
#12121 on JY-20963-fix-im Project: faVsco.js, menu
#12121 on JY-20963-fix-import-on-deleted-entity, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
FirefoxFileEditViewHistoryBookmarksProfilesToolsWindowHelpec2-user@ip-10-30-129-190:~screenpipe"‹$0(ah]100% <78• Thu 28 May 15:12:54181ec2-user@ip-10-30-140-…₴7DOCKER#_####_#####\\###||\#/V~'881DEV (-zsh)O [EMAIL] Linux 2023 (ECS Optimized)_/m/For documentation, visit [URL_WITH_CREDENTIALS] ~]$ exitlogoutConnection to jiminny-prod-ecsi closed.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ applukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ vprodWarning: Permanently added 'jiminny-prod-ecs1' (ED25519) to the list of known hosts.A newer release of "Amazon Linux" is available.Version 2023.10.20260330:Version 2023.11.20260406:Version 2023.11.20260413:Version2023.11.20260427:Version2023.11.20260505:Version 2023.11.20260509:Version 2023.11.20260511:Version 2023.11.20260514:Run "/usr/bin/dnf check-release-update" for full release and version update info#_~\ ####_\ #####\\###1\#/Amazon Linux 2023 (ECS Optimized)/m/'For documentation, visit [URL_WITH_CREDENTIALS] ~]$ client_loop: send disconnect: Broken pipeukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-relay) $I...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85218
|
2918
|
61
|
2026-05-28T12:12:50.898182+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779970370898_m1.jpg...
|
PhpStorm
|
faVsco.js – Client.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
#12121 on JY-20963-fix-im Project: faVsco.js, menu
#12121 on JY-20963-fix-import-on-deleted-entity, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
2
69
3...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12121 on JY-20963-fix-import-on-deleted-entity, menu","depth":5,"on_screen":true,"help_text":"Pull request #12121 exists for current branch JY-20963-fix-import-on-deleted-entity","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"TextRelayServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'TextRelayServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"2","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"69","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"3","depth":4,"on_screen":true,"role_description":"text"}]...
|
-45081608812797713
|
-8776120261847823424
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
#12121 on JY-20963-fix-im Project: faVsco.js, menu
#12121 on JY-20963-fix-import-on-deleted-entity, menu
Start Listening for PHP Debug Connections
TextRelayServiceTest
Run 'TextRelayServiceTest'
Debug 'TextRelayServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
2
69
3
FirefoxFileEditViewHistoryBookmarksProfilesToolsWindowHelpec2-user@ip-10-30-129-190:~screenpipe"O &4‹$0(ah]A100% <78 • Thu 28 May 15:12:50181ec2-user@ip-10-30-140-...₴7DOCKER#_####_#####\\###||\#/V~'881DEV (-zsh)O [EMAIL] Linux 2023 (ECS Optimized)_/m/For documentation, visit [URL_WITH_CREDENTIALS] ~]$ exitlogoutConnection to jiminny-prod-ecsi closed.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~ $ applukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ vprodWarning: Permanently added 'jiminny-prod-ecs1' (ED25519) to the list of known hosts.A newer release of "Amazon Linux" is available.Version 2023.10.20260330:Version 2023.11.20260406:Version 2023.11.20260413:Version2023.11.20260427:Version2023.11.20260505:Version 2023.11.20260509:Version 2023.11.20260511:Version 2023.11.20260514:Run "/usr/bin/dnf check-release-update" for full release and version update info#_~\ ####_\ #####\\###1\#/Amazon Linux 2023 (ECS Optimized)/m/'For documentation, visit [URL_WITH_CREDENTIALS] ~]$ client_loop: send disconnect: Broken pipeukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20915-fix-missing-header-text-relay) $I...
|
85216
|
NULL
|
NULL
|
NULL
|