Как стать автором
Обновить

Комментарии 18

Это не решает проблему, т.к. timestamp миграции 2го комита может раньше timespamp'а миграции 1го, а миграции должны выполняться последовательно, иначе будет undefined behavior :)


У меня другой совет Сэмам и Бобам: раз уж сидите на дотнете, используйте EF-миграции.
Перед комитом с миграцией, заливайте в свой фиче-бран последние изменения и если там есть новая миграция, просто перегенерируйте свою. Это делается несложным скриптом:
1 Update-Database -TargetMigration "before"
2 удаляем свою миграцию
3 Add-Migration "myNewMigration"
Тогда не надо будет договариваться, менять числа на сервере, ставить хуки, вы не будете блокировать друг друга и если миграции затрагивают одни и те же таблицы, у вас будет возможность решить конфликты.


P.S. доки по теме: https://docs.microsoft.com/ru-ru/ef/ef6/modeling/code-first/migrations/teams


P.P.S.
Еще можно "огородить" работу с БД отдельным интерфейсом/сервисом и делегировать это специально выделенному человеку. Остальные будут работать с ней только через интерфейс/RPC используя временные "затычки".
Или банально делать более мелкие комиты. Проблема останется, но разруливать мелкие конфлиты гораздо проще и экономнее для нервной системы :)

Это не решает проблему, т.к. timestamp миграции 2го комита может раньше timespamp'а миграции 1го, а миграции должны выполняться последовательно, иначе будет undefined behavior :)

Можно сортировать не по timestamp, а по имени файла без %login%

Я это и имел ввиду, т.к. timestamp зашит в имени.
Но как это решает проблему?
Сэм начал разработку 10го числа, закомитил 20го, Боб начал 15го, закомитил 16го. в итоге сначала выполняетя миграция от 15го числа, а потом от 10го.
Или я что-то недопонял?

EF-миграции создают сущий кошмар в ситуации, когда параллельно разрабатывается несколько фич и в develop они сливаются в одном порядке, а в master — в другом.

Имхо, если вы так делаете, то тут и с EF и без будет кошмар.
Обычно разработка ведется в фиче бранче, потом заливается в develop, а develop вливают в master fast-forward'ом и проблем быть не должно

Фичи вливаются в develop когда их сделал разработчик, а в master — когда они полностью протестированы и готовы к релизу. Поэтому мержить develop в master (по крайней мере у нас) строго-настрого запрещено: иначе в релиз может проскочить сломанная фича.


Проблема именно в том, что EF нужен полный "слепок" текущего состояния БД для миграций. Поэтому если просто использовать EF без миграций, заменяя их SQL-скриптами и сторонними утилитами типа FluentMigrator, проблема не возникает.

Я вас понял. У нас есть отведенное для тестирования время и в конце спринта всё вливается в master, либо спринт проливается. Если нужна доработка создается отдельная фикс-миграция. Проблем с EF не наблюдаем.
Раз у вас принятно вливать по отдельности, наверное, EF не самый удачный выбор.
Но он делает так не потому что он "плохой", а потому что такой подход дает гарантию не сломать БД при мерже.
А как вы решаете такую проблему?
Фича в девелопе готова к мержу в мастер, но в develop'е уже есть другие миграции, которые пока не готовы и связанны с вашей?

В проектах поменьше решаем административно — задачи ставятся так, чтобы параллельных миграций не было, и релизятся в той же последовательности.


В проектах побольше пишем миграции руками в виде SQL-скриптов. При этом для доступа к данным все равно используем EF, но без миграций. Оба варианта уже несколько лет исправно работают.

Фичи вливаются в develop после тестирования QA и не должны там быть не оттестированными. При релизе всё уже оттестированное из develop сливается в master и тестируется уже на проде.

А тестируются они где? У вас разворачивается полная копия окружения под каждую фичу? И как вы потом тестируете, что они не конфликтуют между собой после мержа?

для тестирования есть так называемые debug окружения. и да, у нас есть около 30 debug окружений, которые занимают по необходимости для тестирования задач перед мержем в develop. develop уже тестируется на staging окружении
stepNNN.sql -> stepYYYY-MM-DD-HHMM-%login%.sql.

Почему не назвать файл более понятным именем, например, feature-XXX.sql или fix-YYY.sql, а с порядком применения миграций разбираться в отдельном оркестрационном скрипте, в явно описанном виде, а не через магические числа с потенциальными конфликтами?

Все, что нужно от этих файлов — сохранить порядок применения. В принципе, можно и feature-xxx, но тогда нужен сервис для определения свободного xxx для исключения конфликтов, вероятность которых выше при таком именовании. В итоге разработка усложняется.

Мне кажется, что получить конфликт c feature-XXX.sql примерно так же маловероятно, как получить конфликт с имеем бранча в репозитории. Имён всяких много, на крайняк XXX может быть/включать номер task-а или issue для пущей уникальности и простоты навигации по коду. Но если что можно и переименовать, на порядок это никак не влияет. А вот последний незадействованный номер — это hot spot, конфликт просто напрашивается.

На всякий случай уточню, что xxx — это не число, а имя фичи или проблемы, например feature-user-logon-reporting.sql. Чтобы тут возник конфликт, нужно чтобы два человека вдруг случайно выбрали совершенно одно и то же длинное имя в пересекающиеся интервалы времени.

Спасибо за статью!
Возможно я чего-то не понимаю, но не могли бы Вы пояснить, почему Вы использовали такую конструкцию, а не механизм await:

.ConfigureAwait(false)
.GetAwaiter()
.GetResult();

Вы совершенно правы, использование await было бы более удобным. Я писал об этом в пункте 5 раздела "Направления дальнейшего развития". Лучше определить интерфейсы hook'ов через Task:


public interface IPreCommitHook
{
    Task<bool> Process(IList<string> args);
}

Тогда в их реализации можно свободно использовать async/await.
Тем не менее, насколько мне известно, сами hook'и не подерживают асинхронные операции, поэтому где-то всё равно придётся дожидаться окончания работы задач.

Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории