ഒരു കാഷഡ് (Cached) റിയാക്ട് ബണ്ടിൽ എങ്ങനെ തെറ്റായ ഡാറ്റാബേസിലേക്ക് ഡാറ്റ എത്തിച്ചു
ഞങ്ങൾ ഒരു ഡെഡ്ലൈൻ പൂർത്തിയാക്കി. ബാക്കെൻഡ് ടീം പുതിയൊരു API-യിലേക്കും പുതിയൊരു ഡാറ്റാബേസിലേക്കും മാറുകയായിരുന്നു. ഫ്രണ്ട്എൻഡ് ടീം AWS Amplify-യിലെ എൻവയോൺമെന്റ് വേരിയബിളുകൾ (environment variables) അപ്ഡേറ്റ് ചെയ്യുകയും കോഡ് പുഷ് ചെയ്യുകയും ചെയ്തു.
ഡിപ്ലോയ്മെന്റ് വിജയകരമായിരുന്നു. ഞങ്ങൾ ലാപ്ടോപ്പുകൾ അടച്ചു. എല്ലാം കഴിഞ്ഞു എന്ന് ഞങ്ങൾ കരുതി.
ഞങ്ങൾ തെറ്റിദ്ധരിച്ചു.
ഒരു എൻജിനീയർ പഴയ API സെർവറിലെ ലോഗുകൾ പരിശോധിച്ചു. ആ സെർവർ പ്രവർത്തനരഹിതമാകേണ്ടതായിരുന്നു. എന്നാൽ അത് അങ്ങനെയായിരുന്നില്ല. അത് യഥാർത്ഥ ക്ലയന്റ് റിക്വസ്റ്റുകൾ സ്വീകരിക്കുകയും പഴയ ഡാറ്റാബേസിലേക്ക് ഡാറ്റ എഴുതുകയും ചെയ്യുന്നുണ്ടായിരുന്നു.
രണ്ട് മണിക്കൂർ നേരം, യഥാർത്ഥ ക്ലയന്റ് ഡാറ്റ തെറ്റായ സ്ഥലത്തേക്ക് പോയിക്കൊണ്ടിരുന്നു.
ഇത് എന്തുകൊണ്ട് സംഭവിച്ചു എന്നും ഞങ്ങൾ ഇത് എങ്ങനെ പരിഹരിച്ചു എന്നും താഴെ നൽകുന്നു.
പ്രശ്നം
AWS Amplify പോലുള്ള CDN-കളിൽ പ്രവർത്തിക്കുന്ന React ആപ്പുകൾ ബിൽഡ് സമയത്താണ് (build time) എൻവയോൺമെന്റ് വേരിയബിളുകൾ മാറ്റുന്നത്. നിങ്ങൾ ഒരു ബിൽഡ് റൺ ചെയ്യുമ്പോൾ, ബണ്ട്ലർ (bundler) ഓരോ വേരിയബിളും കണ്ടെത്തി അവയെ ഒരു ഹാർഡ്കോഡഡ് സ്ട്രിംഗായി (hardcoded string) മാറ്റുന്നു.
API URL നേരിട്ട് JavaScript ഫയലിൽ ഉൾപ്പെടുത്തിയിരിക്കുകയായിരുന്നു.
ഞങ്ങൾ ഡിപ്ലോയ് ചെയ്തപ്പോൾ, പുതിയ ഉപയോക്താക്കൾക്ക് പുതിയ ബണ്ടിൽ ലഭിച്ചു. എന്നാൽ ആപ്പ് തുറന്നു വെച്ചിരുന്ന നിലവിലുള്ള ഉപയോക്താക്കൾ അത് റീഫ്രഷ് ചെയ്തില്ല. പഴയ URL ഹാർഡ്കോഡ് ചെയ്ത പഴയ ബണ്ടിൽ തന്നെ അവർ തുടർന്നും ഉപയോഗിച്ചുകൊണ്ടിരുന്നു.
പഴയ സെർവർ ഇപ്പോഴും പ്രവർത്തിച്ചുകൊണ്ടിരുന്നതിനാൽ, ഈ ക്ലയന്റുകൾക്ക് 200 OK സ്റ്റാറ്റസ് ലഭിച്ചു. എല്ലാം ശരിയാണെന്ന് തോന്നിപ്പിച്ചു. എന്നാൽ ഈ പരാജയം ആരും അറിയാതെ സംഭവിച്ചതായിരുന്നു (silent failure). ഇത്തരം നിശബ്ദമായ പിഴവുകളാണ് ഏറ്റവും അപകടകരമായ ബഗുകൾ.
മൂന്ന് പാളികളുള്ള പരിഹാരം
ഇത് ഇനി ഒരിക്കലും സംഭവിക്കില്ലെന്ന് ഉറപ്പാക്കാൻ ഞങ്ങൾ മൂന്ന് പാളികൾ തയ്യാറാക്കി.
1. റൺടൈം കോൺഫിഗറേഷൻ
JavaScript ബണ്ടിലിൽ URL ഉൾപ്പെടുത്തുന്നത് ഞങ്ങൾ നിർത്തി. പകരം, public ഫോൾഡറിൽ ഒരു config.json ഫയൽ ഉപയോഗിക്കുന്നു. ബണ്ട്ലർ ഈ ഫയലിൽ മാറ്റങ്ങൾ വരുത്തുന്നില്ല. ആപ്പ് റെൻഡർ ചെയ്യുന്നതിന് മുമ്പ് റൺടൈമിൽ ഈ ഫയൽ ആപ്പ് ഫെച്ച് ചെയ്യുന്നു. ഇത് പുതിയ സെഷനുകൾക്ക് എപ്പോഴും ശരിയായ URL ലഭിക്കുന്നുവെന്ന് ഉറപ്പാക്കുന്നു.
2. വെബ്സോക്കറ്റ് നോട്ടിഫിക്കേഷനുകൾ ആപ്പ് തുറന്നു വെച്ചിരിക്കുന്ന ഉപയോക്താക്കളെ റൺടൈം കോൺഫിഗറേഷൻ കൊണ്ട് സഹായിക്കാൻ കഴിയില്ല. അതിനാൽ ഞങ്ങൾ ഞങ്ങളുടെ ഡിപ്ലോയ്മെന്റ് പ്രക്രിയയെ WebSocket സെർവറുമായി ബന്ധിപ്പിച്ചു. Amplify ഒരു ബിൽഡ് പൂർത്തിയാക്കുമ്പോൾ, അത് ഞങ്ങളുടെ API-യിലെ ഒരു വെബ്ഹുക്ക് (webhook) വിളിക്കുന്നു. തുടർന്ന് സെർവർ കണക്റ്റഡ് ആയ എല്ലാ ക്ലയന്റുകൾക്കും ഒരു സന്ദേശം അയക്കുന്നു. ഉപയോക്താവ് പഴയ വേർഷനിലാണ് ഉപയോഗിക്കുന്നതെങ്കിൽ, പേജ് റീഫ്രഷ് ചെയ്യാൻ ആവശ്യപ്പെട്ടുകൊണ്ട് ഒരു ബാനർ കാണിക്കും.
3. കാഷെ മാനേജ്മെന്റ്
ഞങ്ങൾ ഞങ്ങളുടെ CloudFront സെറ്റിംഗുകൾ അപ്ഡേറ്റ് ചെയ്തു. index.html, config.json തുടങ്ങിയ എൻട്രി പോയിന്റുകൾ ഇപ്പോൾ no-cache ആയി ക്രമീകരിച്ചിരിക്കുന്നു. ഇത് ഉപയോക്താക്കൾക്ക് CDN എഡ്ജ് നോഡുകളിൽ നിന്ന് പഴയ ഫയലുകൾക്ക് പകരം എപ്പോഴും ഏറ്റവും പുതിയ ഫയലുകൾ ലഭിക്കുന്നുവെന്ന് ഉറപ്പാക്കുന്നു.
പാഠങ്ങൾ
• ഡിപ്ലോയ്മെന്റുകൾക്കിടയിൽ മാറുന്ന മൂല്യങ്ങൾക്ക് ബിൽഡ്-ടൈം കോൺഫിഗറേഷൻ (Build-time config) ഒരു കെണിയാണ്. • നിശബ്ദത ശബ്ദത്തേക്കാൾ അപകടകാരിയാണ്. പഴയ സിസ്റ്റങ്ങൾ 410 Gone സ്റ്റാറ്റസ് ഉപയോഗിച്ച് വ്യക്തമായി പരാജയപ്പെടുന്നു എന്ന് ഉറപ്പാക്കുക. • സമയപരിധിയുടെ സമ്മർദ്ദം മാനുവൽ ഘട്ടങ്ങളിൽ പിഴവുകൾ വരുത്തിവിടും. നിങ്ങളുടെ ഡി കമ്മീഷനിംഗ് (decommissioning) പ്രക്രിയ ഓട്ടോമേറ്റ് ചെയ്യുക. • നിങ്ങൾ പുതിയതായി പ്രവർത്തനക്ഷമമാക്കുന്ന കാര്യങ്ങൾ മാത്രമല്ല, നിർത്തലാക്കുന്ന കാര്യങ്ങളും നിരീക്ഷിക്കുക.
ഡിപ്ലോയ്മെന്റ് എന്നത് വെറും കോഡ് പുഷ് ചെയ്യുന്നത് മാത്രമല്ല. ഓരോ ക്ലയന്റും ശരിയായ കോഡ് തന്നെ പ്രവർത്തിപ്പിക്കുന്നുണ്ടെന്ന് ഉറപ്പാക്കുന്നതിനെക്കുറിച്ചുകൂടിയാണ് അത്.
സ്രോതസ്സ്: https://dev.to/sugan_dev/how-a-cached-react-bundle-sent-production-data-to-the-wrong-database-55n9