Publish రెండుసార్లు నొక్కితే ఇప్పుడు ఒక్కసారే పబ్లిష్ అవుతుంది
ఒకే యాప్ కోసం మూడు పబ్లిష్ అభ్యర్థనలు 84 మిల్లీసెకన్ల తేడాతో మా API కి చేరాయి, మరియు ప్రతిదీ ఆ యాప్ యొక్క పూర్తి డిప్లాయ్ను ప్రారంభించింది. అవి ఒకే హోస్టింగ్పై ఒకదానితో ఒకటి పోటీపడ్డాయి, ఫలితంగా వచ్చిన రిలీజ్లలో చాలావరకు మరొకటి ముందుగా చేరినందున విఫలమయ్యాయి, మరియు కనిపించిన ఒకే సంకేతం “release failed” ఇమెయిల్ — యాప్ స్వయంగా చివరికి బాగానే ఉంది. ఇప్పుడు ఒకే యాప్ కోసం పబ్లిష్ నడుస్తుండగా మరొకటి వస్తే, రెండో బిల్డ్ మొదలుకాదు. ఏ అభ్యర్థన గెలుస్తుందో డేటాబేస్ నిర్ణయిస్తుంది, మిగతావారికి నిజం చెప్పబడుతుంది: ఇప్పటికే ఒక పబ్లిష్ నడుస్తోంది.
ఏమి జరిగింది
మీరు Mythex లో ఒక యాప్ను పబ్లిష్ చేసినప్పుడు, API దాని కోసం ఒక డిప్లాయ్మెంట్ రికార్డ్ చేస్తుంది, మరియు బిల్డ్లను నడిపే మా సర్వీస్ అయిన ఆర్కెస్ట్రేటర్ను దానిని బిల్డ్ చేసి రిలీజ్ చేయమని అడుగుతుంది. పబ్లిష్ Publish బటన్ నుండి, మరో బ్రౌజర్ ట్యాబ్ నుండి, లేదా మీరు అడిగినప్పుడు ఏజెంట్ నుండి ప్రారంభం కావచ్చు. డబుల్ క్లిక్, రెండు ట్యాబ్లు, లేదా రెండుసార్లు వచ్చిన ఏజెంట్ అభ్యర్థన — ఇవన్నీ దాదాపు ఒకే క్షణంలో ఒకే యాప్ కోసం ఒకటి కంటే ఎక్కువ పబ్లిష్లకు దారితీయగలవు.
ఈ సందర్భంలో, మూడు 84 ms లోపే వచ్చాయి. ప్రతిదీ పూర్తి డిప్లాయ్ నడిపింది. హోస్టింగ్ ప్లాట్ఫామ్లో, అదే యాప్ కోసం రిలీజ్లు ఒకే సెకనులో సృష్టించబడ్డాయి, మరియు వాటిలో మూడు ఇతరులు ఇప్పటికే జరుగుతున్నందున విఫలమయ్యాయి. ఒక తర్వాతి రిలీజ్ అతుక్కుపోయింది, మరియు తర్వాత యాప్ పనిచేసింది.
అదే దానిని గమనించడం కష్టం చేసింది. వినియోగదారుకు ఒక పనిచేసే యాప్ కనిపించింది. వైఫల్యాలు కేవలం release-failure ఇమెయిల్లలో మాత్రమే కనిపించాయి.
ఏదీ ఎందుకు ఆపలేదు
పబ్లిష్ కోడ్కు ప్రాజెక్ట్ కోసం జరుగుతున్న డిప్లాయ్లను చూసే ఒక దశ ఉంది. కానీ అది చేసేది ఏమిటంటే, ప్రారంభించే ముందు జరుగుతున్న ప్రతి డిప్లాయ్ను విఫలంగా గుర్తించడం — “కొత్త పబ్లిష్ ద్వారా భర్తీ చేయబడింది”. అది క్రాష్ అయిన ప్రాసెస్ వదిలేసిన బిల్డ్లను శుభ్రం చేయడానికి ఉద్దేశించబడింది.
ఆచరణలో, బిల్డ్ మధ్యలో వచ్చిన రెండో పబ్లిష్ మొదటిది చనిపోయిందని ప్రకటించి తన సొంతదాన్ని ప్రారంభించేది. రెండూ ఒకే యాప్కు వ్యతిరేకంగా పూర్తయ్యేవి. ఎటువంటి లాక్ లేదు; దారిని చురుగ్గా క్లియర్ చేసే ఒక దశ మాత్రమే ఉంది.
యాప్ యొక్క మొట్టమొదటి పబ్లిష్కు రెండో, వింత లక్షణం ఉంది. ఇంకా ఉపయోగించడానికి డిప్లాయ్మెంట్ రికార్డ్ లేనప్పుడు, ఒకేసారి వచ్చిన రెండు మొదటి పబ్లిష్లు ఒకే రికార్డ్ను చొప్పించడానికి ప్రయత్నించాయి. డేటాబేస్కు యాప్ లింక్ పేరు (దాని slug, ఉదాహరణకు your-app.mythex.ai లోని your-app) పై ప్రత్యేక ఇండెక్స్ ఉంది, కాబట్టి రెండో చొప్పింపు విఫలమైంది. API దానిని “ఆ లింక్ పేరు తీసుకోబడింది” గా అనువదించింది — అప్పుడు విజయవంతంగా ఆ పేరుతో పబ్లిష్ అవుతున్న యాప్కు పేరు మార్చమని వినియోగదారుకు సలహా ఇస్తూ.
పరిష్కారం: క్లెయిమ్ అనేదే లాక్
డిప్లాయ్మెంట్ రికార్డ్ను క్లెయిమ్ చేయడం ఇప్పుడు ఒకే షరతు ఉన్న డేటాబేస్ అప్డేట్: ఈ వరుసను తీసుకుని, ఎవరూ పబ్లిష్ చేయనప్పుడు మాత్రమే building గా గుర్తించు. అది ఒకే స్టేట్మెంట్ కాబట్టి, డేటాబేస్ ఒకే మిల్లీసెకనులో వచ్చే అభ్యర్థనలను పరిష్కరిస్తుంది. ఖచ్చితంగా ఒకటి మాత్రమే వరుసను మారుస్తుంది. మిగతావి ఏ వరుసా మారలేదని చూసి ఆగిపోతాయి, మరియు ఆర్కెస్ట్రేటర్ను ఎప్పుడూ చేరవు.
లాక్కు దాని హోల్డర్ చనిపోయినప్పుడు బయటపడే మార్గం కూడా అవసరం. API పబ్లిష్ మధ్యలో రీస్టార్ట్ అయితే, వరుస ఎప్పటికీ “building” గా ఉండిపోతుంది, మరియు యాప్ పబ్లిష్ చేయలేనిదిగా మారుతుంది. కాబట్టి హార్ట్బీట్లు పంపడం ఆగిపోయిన యజమాని ఉన్న వరుసను — నడుస్తున్న పబ్లిష్ ప్రతి 30 సెకన్లకు వరుసను అప్డేట్ చేస్తుంది, మరియు ఐదు నిమిషాల నిశ్శబ్దం చనిపోయినట్లు లెక్కించబడుతుంది — మళ్లీ క్లెయిమ్ చేయవచ్చు. ఆ థ్రెష్హోల్డ్ హార్ట్బీట్ నుండే వస్తుంది, బిల్డ్ ఎంత సమయం పడుతుందో అంచనా నుండి కాదు. వినియోగదారు స్వంత Dockerfile ను బిల్డ్ చేయడం చట్టబద్ధంగా చాలా సమయం తీసుకోవచ్చు, మరియు హార్ట్బీట్ చేస్తూనే ఉన్న నెమ్మది బిల్డ్ తన క్లెయిమ్ను ఉంచుకుంటుంది.
ప్రతి పబ్లిష్ ముందు మధ్యలో ఉన్న డిప్లాయ్లన్నింటినీ విఫలంగా గుర్తించే అడుగు ఇప్పుడు నడవదు. చనిపోయిన ప్రాసెస్ వదిలేసిన వరుసలు మాత్రమే క్లియర్ చేయబడతాయి.
ఓడిపోయిన వారికి నిజం చెప్పడం
ఓడిపోయిన అభ్యర్థనకు ఇప్పుడు స్పష్టమైన సమాధానం వస్తుంది: publish_in_progress, దానితో పాటు నడుస్తున్న డిప్లాయ్మెంట్ ID. పబ్లిష్ ప్రారంభించగల ప్రతి స్థలం దానిని నిర్వహిస్తుంది:
- వర్క్స్పేస్ దానిపై ఎర్రర్ చూపించకుండా, ఇప్పటికే నడుస్తున్న బిల్డ్ను అనుసరిస్తుంది.
- ఏజెంట్కు ఈ యాప్ యొక్క పబ్లిష్ ఇప్పటికే నడుస్తోందని, దాని కోసం వేచి ఉండమని చెప్పబడుతుంది — ఏదో విఫలమైందని చెప్పబడటం కాదు, ఇది ముందు అతన్ని Dockerfile ను “ఫిక్స్” చేయడానికి పంపి మళ్లీ ప్రయత్నించేలా చేయగలదు.
- మొదటి పబ్లిష్ లింక్ పేరు ఘర్షణ తనిఖీ చేయబడుతుంది: లింక్ పేరును కలిగి ఉన్న వరుస ఈ ప్రాజెక్ట్ యొక్క సొంత నడుస్తున్న పబ్లిష్ అయితే, సమాధానం “ఇప్పటికే పబ్లిష్ అవుతోంది”, “ఆ పేరు తీసుకోబడింది” కాదు. మరొక ప్రాజెక్ట్తో నిజమైన ఘర్షణ ఇప్పటికీ పేరు మార్చమనే సందేశాన్ని పొందుతుంది.
మేము దీన్ని ఎలా తనిఖీ చేశాం
మేము ఒక పునరుత్పత్తి స్క్రిప్ట్ రాశాం, అది నిజమైన డేటాబేస్ మరియు ఒక స్టబ్ ఆర్కెస్ట్రేటర్కు వ్యతిరేకంగా ఒకే యాప్ యొక్క మూడు పబ్లిష్లను ఒకేసారి నడిపి, ఆర్కెస్ట్రేటర్ ఎన్ని డిప్లాయ్లు కోరుతోందో లెక్కిస్తుంది. అది మొదటి పబ్లిష్ మరియు ప్రత్యక్షంగా ఉన్న యాప్ యొక్క రీ-పబ్లిష్ను కవర్ చేస్తుంది. పరిష్కారానికి ముందు, అది రెండు డిప్లాయ్లను లెక్కించింది. తర్వాత, ఒకటి.
స్క్రిప్ట్ తప్పించుకునే మార్గాన్ని కూడా కవర్ చేస్తుంది: యాప్ వరుసను పది నిమిషాల పాటు హార్ట్బీట్ లేకుండా building గా గుర్తిస్తుంది, మళ్లీ పబ్లిష్ చేస్తుంది, మరియు కొత్త పబ్లిష్ వరుసను క్లెయిమ్ చేసి నడుస్తుందో లేదో తనిఖీ చేస్తుంది.
యూనిట్ పరీక్షలు లాక్ను అది చేయవలసిన రెండు పనులకు పరిమితం చేస్తాయి: ఒకేసారి వచ్చిన మూడు రీ-పబ్లిష్లలో, ఖచ్చితంగా ఒకటి ముందుకు వెళ్తుంది, మరియు మిగతా రెండుకు పబ్లిష్ నడుస్తోందని చెబుతారు; మరియు యజమాని చనిపోయిన బిల్డ్ను క్లెయిమ్ చేయవచ్చు. మరొక పరీక్ష కొత్త ప్రయత్నం మునుపటి ప్రయత్నం యొక్క ఎర్రర్ సందేశాన్ని మోసుకెళ్లదని తనిఖీ చేస్తుంది.
మేము నేర్చుకున్నది
- క్లీనప్ కోడ్ మారువేషంలో రేస్ కావచ్చు. “మధ్యలో ఉన్నవన్నీ విఫలం చేయి, తర్వాత ప్రారంభించు” అది పరిశుభ్రతలా కనిపిస్తుంది. ఇద్దరు కాలర్లు ఉన్నప్పుడు, అది ఒకరు మరొకరిని రద్దు చేయడం.
- డేటాబేస్ను మధ్యవర్తిగా ఉంచండి. చదవడం తర్వాత రాయడం మరో అభ్యర్థనకు గ్యాప్ వదులుతుంది. ఒకే షరతు ఉన్న అప్డేట్ అలా చేయదు.
- ప్రతి లాక్కు జీవన సంకేతంతో ముడిపడిన గడువు ఉండాలి. అది లేకుండా, క్రాష్ అతుక్కుపోయిన యాప్గా మారుతుంది.
- ఎర్రర్ సందేశాలు సూచనలు. “ఆ పేరు తీసుకోబడింది” ప్రజలను తప్పు పని చేయమని చెప్పింది. సరైన సందేశం సరళమైనది మరియు నిజమైనది.
పబ్లిషింగ్ గురించి డాక్స్లో మరింత: how to publish. మరియు సంబంధిత పరిష్కారం: మీ ప్రచురించిన యాప్ మీరు రీ-పబ్లిష్ చేస్తున్నప్పుడు కూడా లైవ్గా ఉంటుంది.