Skip to content

Commit d741ed5

Browse files
Alexey PortnovAlexey Portnov
authored andcommitted
Fix: дубли контактов при параллельных AmoCdrDaemon, CSS leak виджета, устаревшие ссылки
- bin/safe.php: flock для предотвращения параллельного запуска воркеров из cron - bin/AmoCdrDaemon.php: flock на cdrSync — только один процесс обрабатывает CDR - bin/AmoCdrDaemon.php: повторная проверка БД перед createContacts (race condition) - widget/css/semantic.css: заменён полный Fomantic UI (74k строк) на минимальный скоупленный CSS под #miko (342 строки) — устранена утечка стилей на кнопки AmoCRM - Обновлена ссылка на документацию wiki.mikopbx.ru → docs.mikopbx.com
1 parent 1c4ef6c commit d741ed5

File tree

5 files changed

+279
-74048
lines changed

5 files changed

+279
-74048
lines changed

bin/AmoCdrDaemon.php

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,32 @@ private function updateActiveCalls():void
277277
* @return void
278278
*/
279279
private function cdrSync():void
280+
{
281+
// Защита от параллельной обработки CDR двумя экземплярами AmoCdrDaemon
282+
$lockFile = '/tmp/amo_cdr_sync.lock';
283+
$lockFp = fopen($lockFile, 'w');
284+
if ($lockFp === false) {
285+
$this->logger->writeError('cdrSync: failed to open lock file');
286+
return;
287+
}
288+
if (!flock($lockFp, LOCK_EX | LOCK_NB)) {
289+
$this->logger->writeInfo('cdrSync is locked by another process, skip this iteration');
290+
fclose($lockFp);
291+
return;
292+
}
293+
try {
294+
$this->cdrSyncInternal();
295+
} finally {
296+
flock($lockFp, LOCK_UN);
297+
fclose($lockFp);
298+
}
299+
}
300+
301+
/**
302+
* Внутренняя логика синхронизации CDR (защищена file lock в cdrSync).
303+
* @return void
304+
*/
305+
private function cdrSyncInternal():void
280306
{
281307
$oldOffset = $this->offset;
282308
$this->cdrRows = [];
@@ -1188,6 +1214,50 @@ private function createContacts(&$calls):void
11881214
if(empty($this->newContacts)){
11891215
return;
11901216
}
1217+
1218+
// Повторная проверка БД: контакт мог быть создан другим процессом между
1219+
// prepareDataCreatingEntities() и этим моментом
1220+
$phonesToCheck = array_keys($this->newContacts);
1221+
$freshData = ConnectorDb::invoke('getContactsData', [$phonesToCheck]);
1222+
if (is_array($freshData)) {
1223+
foreach ($freshData as $phoneId => $data) {
1224+
if (!empty($data['contactId'])) {
1225+
$this->logger->writeInfo("Contact already exists for $phoneId (id:{$data['contactId']}), skip create");
1226+
$contactId = intval($data['contactId']);
1227+
// Привязываем существующий контакт к связанным сущностям
1228+
if (isset($this->newLeads[$phoneId])) {
1229+
$this->newLeads[$phoneId]['_embedded']['contacts'][] = [
1230+
'id' => $contactId,
1231+
'is_main' => true
1232+
];
1233+
}
1234+
if (isset($this->newUnsorted[$phoneId])) {
1235+
$this->newUnsorted[$phoneId]['_embedded']['contacts'][] = [
1236+
'id' => $contactId,
1237+
];
1238+
}
1239+
if (isset($this->newTasks[$phoneId])) {
1240+
$this->newTasks[$phoneId]['entity_id'] = $contactId;
1241+
$this->newTasks[$phoneId]['entity_type'] = 'contact';
1242+
}
1243+
if (isset($this->incompleteAnswered[$phoneId])) {
1244+
$this->incompleteAnswered[$phoneId]['client'] = $contactId;
1245+
}
1246+
if (isset($calls[$phoneId])) {
1247+
foreach ($calls[$phoneId] as &$call) {
1248+
$call['entity_id'] = $contactId;
1249+
}
1250+
unset($call);
1251+
}
1252+
unset($this->newContacts[$phoneId]);
1253+
}
1254+
}
1255+
}
1256+
1257+
if(empty($this->newContacts)){
1258+
return;
1259+
}
1260+
11911261
$contactsData = [
11921262
'add' => []
11931263
];

bin/safe.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,18 @@
2929
if(!$moduleEnable){
3030
exit(1);
3131
}
32+
33+
// Защита от параллельного запуска нескольких экземпляров safe.php (cron race condition)
34+
$lockFile = '/tmp/amo_safe.lock';
35+
$lockFp = fopen($lockFile, 'w');
36+
if ($lockFp === false || !flock($lockFp, LOCK_EX | LOCK_NB)) {
37+
// Другой экземпляр safe.php уже работает
38+
if ($lockFp !== false) {
39+
fclose($lockFp);
40+
}
41+
exit(0);
42+
}
43+
3244
$conf = new AmoCrmConf();
3345
$workers = $conf->getModuleWorkers();
3446
foreach ($workers as $workerData) {
@@ -67,3 +79,6 @@
6779
}
6880
}
6981
}
82+
83+
flock($lockFp, LOCK_UN);
84+
fclose($lockFp);

sites/other/widget-desc.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
<li>Вызов абонента АТС двойным кликом в панели управления вызовами</li>
3333
<li>Пропущенные вызовы попадают в неразобранное</li>
3434
</ul>
35-
<a href="https://wiki.mikopbx.ru/module-amo-crm">Инструкции по настройке</a>
35+
<a href="https://docs.mikopbx.com/mikopbx/modules/miko/amocrm">Инструкции по настройке</a>
3636
</div>
3737
</article>
3838

0 commit comments

Comments
 (0)