Publish-ті екі рет басқанда енді бір рет жарияланады
Бір қолданба үшін үш жариялау сұрауы API-мізге 84 миллисекунд аралықпен жетті, әр сұрау сол қолданбаның толық деплойын бастады. Олар бір хостингке бір уақытта кірісіп, нәтижесінде бірнешеуі басқасы бұрын жеткендіктен сәтсіз аяқталды, ал жалғыз көрінетін белгі — «release failed» хаты болды. Қолданбаның өзі соңында дұрыс жұмыс істеді. Енді бір қолданба үшін жариялау жүріп жатқанда келген басқа жариялау екінші құрастыруды бастамайды. Дерекқор қайсысы жеңетінін шешеді, ал қалғандары шындықты біледі: жариялау қазірдің өзінде жүріп жатыр.
Не болды
Mythex-те қолданбаны жариялағанда API деплой жазбасын жазады және құрастыруды, релизді басқаратын қызметті — оркестраторды — сұрайды. Жариялау Publish түймесінен, басқа браузер қойындысынан немесе сіз сұрағанда агенттен басталуы мүмкін. Екі рет басу, екі қойынды немесе екі рет келген агент сұрауы — бәрі бір қолданба үшін бірден бірнеше жариялау тудыруы мүмкін.
Бұл жағдайда үшеуі 84 мс ішінде келді. Әр қайсысы толық деплой бастады. Хостинг платформасында бір қолданбаның релиздері бір секундта жасалды, ал үшеуінің біреуі басқалары бұрыннан орындалып жатқандықтан сәтсіз болды. Соңғы релиз тұрып қалды, бірақ қолданба кейін жұмыс істеді.
Дәл осы себептен мәселені байқау қиын болды. Пайдаланушы бір жұмыс істейтін қолданбаны көрді. Қателер тек «release failed» хаттарында көрінді.
Неге ешнәрсе тоқтатпады
Жариялау кодында жобаның орындалып жатқан деплойларын қарайтын қадам болған. Бірақ ол жүргізген нәрсе — басталар алдында орындалып жатқан әрбір деплойды сәтсіз деп белгілеу еді, «жаңа жариялау арқылы ауыстырылды» деген себеппен. Ол өлген процесс қалдырған құрастыруларды тазарту үшін жасалған еді.
Іс жүзінде жариялау кезінде келген екінші жариялау бірінші құрастыруды өлді деп жариялап, өзінің құрастыруын бастайтын. Екеуі де бір қолданбаға қарсы аяқталуға дейін жүретін. Құлып болмаған; бір-бірін алып тастайтын, жарысқа жол ашатын қадам болған.
Бірінші жариялауға арналған тағы бір, одан да бөтен симптом болды. Деплой жазбасы әлі жоқ кезде, екі бірінші жариялау бір жазбаны қосуға тырысты. Дерекқордың қолданба сілтемесінің атауына (slug, мысалы your-app.mythex.ai ішіндегі your-app) бірегей индексі бар, сондықтан екінші қосу сәтсіз болды. API бұны «бұл сілтеме атауы бос емес» деп аударды және пайдаланушыға дәл сол сәтте сол атаумен сәтті жарияланып жатқан қолданбаны қайта атауды ұсынды.
Түзету: талап — құлып
Деплой жазбасын талап ету енді бір шартты дерекқор жаңартуы: осы жолды тек оны ешкім жарияламаса ғана құрастыру күйіне қою. Бұл бір сұрау болғандықтан, дерекқор бір миллисекундта келген сұрауларды шешеді. Бір ғана сұрау жолды өзгертеді. Қалғандары нөл жолдың өзгергенін көреді, тоқтайды және оркестраторға ешқашан жетпейді.
Құлыпқа иесі өлгенде шығатын жол да керек. Егер API жариялау барысында қайта іске қосылса, жол «құрастырылуда» күйінде мәңгі қалады, ал қолданбаны қайта жариялау мүмкін болмайды. Сондықтан жүгіртілген жариялау жолды әр 30 секунд сайын жаңартады, және бес минут үнсіздік өлі деп есептеледі. Бұл шек жүрек соғысынан келеді, құрастыру қанша уақыт алатынына деген болжамнан емес. Пайдаланушының өз Dockerfile-ы бойынша құрастыру ұзақ жүруі мүмкін, ал жүрек соғысын жіберіп тұрған баяу құрастыру талабын сақтайды.
Деплойды тоқтататын қадам енді жариялау алдында жұмыс істемейді. Тек өлі процесс қалдырған жолдар тазаланады.
Жеңілген сұрауға шындықты айту
Жеңілген сұрау енді анық жауап алады: publish_in_progress, жүріп жатқан деплойдың ID-і қоса. Жариялауды бастай алатын әр орын оны өңдейді:
- Жұмыс кеңістігі қазірдің өзінде жүріп жатқан құрастыруды бақылайды, оның үстінен қате көрсетпейді.
- Агентке қолданбаның жариялауы жүріп жатқаны және соны күту керектігі айтылады, ал бұрын ол қате туралы айтылып, Dockerfile-ды «түзетіп» қайта көруге итермеленуі мүмкін еді.
- Бірінші жариялаудың атау соғысы тексеріледі: егер атауды ұстап тұрған жол осы жобаның өз жүріп жатқан жариялауы болса, жауап «жарияланып жатыр», «атау бос емес» емес. Басқа жобамен шынайы соғыс болса, атауды өзгерту туралы хабарлама әлі шығады.
Қалай тексердік
Бір қолданбаның үш жариялауын нақты дерекқорда және жалғанған оркестраторда бір уақытта іске қосатын қайта жасау скриптін жаздық, және оркестратор қанша деплой сұрағанын санадық. Ол бірінші жариялау мен тірі қолданбаның қайта жариялауын қамтиды. Түзетуге дейін екі деплой саналды. Кейін — бір.
Скрипт шығу жолын да қамтиды: қолданбаның жолын құрастыру күйіне қойып, ешқандай жүрек соғысынсыз он минут бойы, сосын қайта жариялап, жаңа жариялаудың жолды алып, іске қосылатынын тексереді.
Бірлік тесттері құлыпты екі нәрсеге сәйкестендіреді: бір уақыттағы үш қайта жариялаудың тек біреуі өтеді, қалған екеуіне жариялау жүріп жатқаны айтылады; және иесі өлген құрастыруды талап етуге болады. Тағы бір тест жаңа әрекеттің алдыңғы әрекеттің қате хабарын алып жүрмейтінін тексереді.
Біз не үйрендік
- Тазалау коды жарыс болуы мүмкін. «Бәрін орындалып жатқанда сәтсіз деп белгілеп, содан кейін бастау» — тазалық сияқты көрінеді. Екі шақырушы болғанда, бұл бір-бірін болдырмау.
- Дерекқорға шешуші болуға рұқсат беріңіз. Оқу, содан кейін жазу арасында басқа сұрауға жол қалады. Бір шартты жаңарту қалдырмайды.
- Әр құлыпқа жүрек соғысына байланған мерзім керек. Оның жоғында ол құлаған кезде қолданба тұрып қалады.
- Қате хабарлары — нұсқаулар. «Бұл атау бос емес» адамдарды дұрыс емес әрекетке жетеледі. Дұрыс хабар қарапайым әрі шынайы болды.
Жариялау туралы көбірек: қалай жариялау керек. Және байланысты түзету: қайта жариялау кезінде жарияланған қолданба қалай тұрақты қалады.