из одной базы данных в другую базу данных
Имеется старая база данных, создали новую базу данных и через микросервис мобильное приложение которое работает часто в режиме оффлайн и в момент сети синхронизируются данные с новой базой данных и потом новая синхронизирует со старой. Делается это все для того, что бы скопировать в течении определенного времени данные которые клиент использует и впоследствии просто удалить старую базу данных, не спрашивайте а почему сразу не иммигрировать, там все очень сложно, базе больше двадцати лет, много разных клиентов сидят на ней.
И вот замеченно, что если приложение которое работает со старой базой отключенно или bug в сети, вообщем если два api не договорили на заднем фоне, то данные просто сохраняются в новой базе и старая потом об этом ничего не узнает, а мобильное приложение отправляет мессаж что мол данные синхронизированны успешно, только вот потом не состыковка с данными случается.
Таким образом мне думается, что необходимо следующее, создать таблицу в новой базе данных с объектами, которые не удалось синхронизировать потом метод в сервисе дополнительный чтобы получать ответ от api 1 и уже при повторном подключении запускать заново объекты для обновления в данной таблице до синхронизации с мобильным приложением.
Вопрос : какие данные должна содержать данная таблица ? И есть ли другие решения
[Key]
public long Id { get; set; }
public long? ObjectId { get; set; }
[ForeignKey(nameof(ObjectId))]
public Object Object { get; set; }
public DateTime Date { get; set; }
// for example if error < 2, check properties, maybe some information is not correct in that object
public int ErrorSynchronization { get; set; }
в старой базе данных бывают "сюрпризы" например однажды приложение выдавало ошибку при сохранении одного эллемента и я заметила, что в базе данных есть ограничения для одного из свойст (varchar 5) а клиент сохраняет например 8 символов, это не было нигде зафиксированно, как уже повторюсь база старая и не мало кто на ней работал...поэтому предусматриваю int ErrorSynchronization, например если первый, второй раз все еще остается не синхронизированным и число int думаю надо +1 возможно надо проанализировать все свойства данного объекта
// api 2 создает таблицы через Entity Framework, работаю я на C#, база на sql => поэтому и метки соответствующие
p.s. вопрос, а тот кто ставит минус это обосновывается, или может быть просто хоп и минус поставил, сама не ставила еще минусы поэтому интересуюсь
Ответы (2 шт):
Можно создать таблицу в новой базе данных с задачами на синхронизацию.
И отдельный синхронизатор, который берет задачи по очереди из новой базы, применяет к старой базе, и хранит номер последней примененной задачи в старой базе.
Изменения и номер последней примененной задачи запишутся в одной транзакции.
после миграции базы данных, мы создали нашу временную таблицу в которой хранятся объекты для повторной синхронизации. (выше в моем вопросе есть пример того, что хранится в данной таблице)
в момент когда мы сохраняем объекты как обычно, если вдруг api1 не ответило, мы сохраняем объекты в данной временной таблице, затем
ДЛЯ ПОВТОРНОЙ ПОПЫТКИ ЗАПИСИ в АПИ1
создаем дополнительный HookController
[HttpGet]
public async Task<ActionResult> RunSynchronizations()
{
await synchronizationService.SendUnsynchronizedObjectsAsync().ConfigureAwait(false);
return Ok();
}
а в нашем api1 в Startup (чтобы как только приложение стало активно) классе зовем данный контроллер (общаются два апи через Refit...) и таким образом как только api1 запускается, api2 просматривает нашу временную таблицу с объектами, которые не были синхронизированны. и повторяет процедуру CRUD (записывает, удаляет, изменяет...)
public Task SendUnsynchronizedObjectsAsync()
{
return Task.Run(() =>
{
var dbSet = dbContext.Set<ObjectsoSendToApi1>(); // наша временная таблица
var objetctsToSynchronize = dbSet.Include(s => s.Object).ToList();
// include чтобы добавить основной объект
Task[] toAwait = new Task[objetctsToSynchronize.Count];
// берем все объекты из временной таблицы
for (var i = 0; i < objetctsToSynchronize.Count; i++)
{
toAwait[i] = SendToApi1ForSaveAsync(objetctsToSynchronize[i].Object);
/* метод SendToApi1ForSaveAsync повторно сохраняет...
и catch если повторно api1 не отвечает и так по кругу... */
}
// и удаляем объекты из временной таблицы
dbSet.RemoveRange(objetctsToSynchronize);
Task.WaitAll(toAwait);
dbContext.SaveChanges(); // сохраняем изменения
});
}