Пакеты восстановления NuGet аварийно завершают работу, когда два параллельных потока пытаются восстановить один и тот же пакет

У меня есть сборка, в которой несколько параллельных этапов начинаются с восстановления NuGet, прежде чем делать разные вещи (сборка и запуск тестов, сборка для iOS, сборка для Android). Восстановление выполняется на каждом этапе, поскольку они могут выполняться на разных агентах сборки. Однако, поскольку в нашей настройке CI есть два исполнителя на агента, они также могут выполняться на одном и том же агенте, и именно здесь возникает моя проблема.

Когда NuGet встречает пакет, которого нет в глобальном каталоге пакетов (~/.nuget/packages, так как я собираю на Mac), он пытается установить его, и это, как правило, происходит одновременно на двух параллельных этапах: вызывая ошибку на одном или обоих этапах. Сообщение об ошибке будет выглядеть следующим образом:

[Stage1] Installing BtDriver 1.0.0. 
[Stage1] WARNING: Error downloading 'BtDriver.1.0.0' from 'https://MyArtifactory/api/nuget/BtDriver/1.0.0'.
[Stage1] Directory /Users/MyUser/.nuget/packages/btdriver/1.0.0/lib is not empty

Или с другого этапа:

[Stage2] Installing BtDriver 1.0.0.
[Stage2] WARNING: Error downloading 'BtDriver.1.0.0' from 'https://MyArtifactory/api/nuget/BtDriver/1.0.0'.
[Stage2] /Users/MyUser/.nuget/packages/btdriver/1.0.0/g45y07q7.6ap does not exist

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

Дополнительная информация: я использую Jenkins для назначения агентов и организации сборки, а NuGet Restore вызывается с помощью Cake's NuGetRestore(), но я могу воспроизвести, используя только "nuget restore" с двух отдельных терминалов одновременно, поэтому я предполагаю, что ошибка не связана с Дженкинсом или Cake, хотя решения, связанные с любым из них, будут приветствоваться.

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


person Andreass    schedule 02.05.2018    source источник
comment
Почему бы вам не восстановить пакеты, а затем собрать их. Было бы полезно, если бы вы поделились тем, как вы создаете эти компоненты.   -  person Liam    schedule 02.05.2018
comment
@liam: мне нужно восстановить непосредственно перед сборкой, потому что три этапа могут выполняться на трех разных агентах. Я не добавлял информацию о сборке, так как ошибка возникает еще до начала сборки, но я могу добавить дополнительную информацию, если это поможет.   -  person Andreass    schedule 02.05.2018


Ответы (2)


У нас есть много агентов CI, работающих на одних и тех же хостах. В конечном итоге мы избавимся от этой проблемы с помощью пользовательской задачи MSBuildWithMutex. https://gist.github.com/dedale/675ec80313f2a70266deb0ab78a0e2c6

person ded'    schedule 26.02.2021

Что бы это ни стоило, мне частично удалось сообщить nuget/msbuild использовать разные пути для своих кешей. См. https://docs.microsoft.com/en-us/nuget/consume-packages/managing-the-global-packages-and-cache-folders для переменных среды.

Однако, преодолев эту проблему, я иногда вижу ошибки сокетов при параллельном восстановлении nuget. Я считаю, что каждый процесс nuget борется за доступ к удаленному серверу и вызывает тайм-ауты.

Я ищу чистый подход - возможно, убедить Дженкинса использовать разные домашние каталоги для каждого исполнителя, чтобы мне не приходилось запускать дополнительный код в каждом задании, но я еще не понял, как это сделать.

person Josh Karabin    schedule 29.03.2019