Я долго пытался выразить словами зачем мне всё это нужно но потом отказался от этой идеи. Кому интересно — отвечу в комментариях. Итак суть:
Существует несколько web-сайтов с похожей базой данных, с похожим функционалом (допустим магазины, продающие одни и те же товары (один владелец).
Нужно: добавить новый товар на все магазины одновременно. Или не добавлять никуда в случае ошибки хотя бы на одном. Если уж совсем по-простому, то ID записей в определенных таблицах должны совпадать на всех сайтах. Например product_id. Опять же скажу — я упростил задачу, на деле все намного сложнее.
Допустим, на каждом сайте существует класс Product и соответствующий метод
То есть на каждом сайте новая запись создается так:
и нам нужно выполнить этот код на всех сайтах-клонах, учитывая, что на одном из них возможна исключительная ситуация, в случае которой запись не должна быть добавлена ни на один из сайтов.
Например:
Вот так вот это и должно выглядеть! Проблема сходиться к тому, что:
Для этого:
Картинка иллюстрирует это:
Подобным образом можно выполнять любой код, например изменение статуса продукта или редактирование карточки. Нужно лишь найти способ передавать код 4code, который нужно выполнить «синхронно на всех клонах» и вызывать eval($code).
Осталась ещё небольшая проблема — как сделать так, чтобы код выполнился [более-менее] одновременно на всех сайтах. Я решил это при помощи nohup, но, думаю, есть и другие способы.
Хотелось бы обсудить всё это с хабрачеловеками.
Существует несколько web-сайтов с похожей базой данных, с похожим функционалом (допустим магазины, продающие одни и те же товары (один владелец).
Нужно: добавить новый товар на все магазины одновременно. Или не добавлять никуда в случае ошибки хотя бы на одном. Если уж совсем по-простому, то ID записей в определенных таблицах должны совпадать на всех сайтах. Например product_id. Опять же скажу — я упростил задачу, на деле все намного сложнее.
Допустим, на каждом сайте существует класс Product и соответствующий метод
class Product
{
...
public static function createNewProduct($productName)
{
if ( self::exists($productName) ) {
throw new Exception('product exists in database');
//выбрасывание исключения добавлено неслучайно
// а для того, чтобы показать что «иногда что-то может пойти не так»
}
$db->execute(
'INSERT INTO products
SET name={$productName}');
$newId = $db->lastInsertId;
return new self($newId);
}
...
}
То есть на каждом сайте новая запись создается так:
<?php
$product = Product::createNewProduct('new product name');
и нам нужно выполнить этот код на всех сайтах-клонах, учитывая, что на одном из них возможна исключительная ситуация, в случае которой запись не должна быть добавлена ни на один из сайтов.
Например:
beginTransaction();
try {
$product = Product::crateateNewProduct('new product name);
commitTransaction();
} catch (Exception $e) {
rollbackTransaction();
throw new Exception('clone-wide code execution failure');
}
Вот так вот это и должно выглядеть! Проблема сходиться к тому, что:
- точно такой же код нужно выполнить одновременно на всех сайтах-клонах;
- функция commitTransaction() не должна сделать «настоящий» commit до тех пор, пока все сайты-клоны не «дадут добро»
- при попадании в функцию rollbackTransaction() хотя бы на одном из клонов, на всех клонах должно сработать исключение, для того, чтобы все сайты «откатились», даже если у них не было ошибок.
Для этого:
- сделаем так, чтобы функции для поддержки «распределенных транзакций» извещали о состоянии транзакции. Например — файл со строкой BEGIN/READY/COMMITED/ROLLBACK доступный извне, например example1.com/transaction/status.txt
- сделаем так, чтобы функция commitTransaction() прежде чем подтвердить MySQL транзакцию «пробежалась» по всем известным сайтам-клонам и проверила, «все ли в порядке» и лишь в этом случае выполнила COMMIT. В противном случае — выбросила бы исключение;
- сделаем так, чтобы функция rollbackTransaction() также сохраняла статус в файл status.txt, для того чтобы другие сайты-клоны могли узнать об этом и «откатиться»
Картинка иллюстрирует это:
Подобным образом можно выполнять любой код, например изменение статуса продукта или редактирование карточки. Нужно лишь найти способ передавать код 4code, который нужно выполнить «синхронно на всех клонах» и вызывать eval($code).
Осталась ещё небольшая проблема — как сделать так, чтобы код выполнился [более-менее] одновременно на всех сайтах. Я решил это при помощи nohup, но, думаю, есть и другие способы.
Хотелось бы обсудить всё это с хабрачеловеками.