ఒక డెవలపర్ CREATE OR REPLACE FUNCTION ఉపయోగించి ఇప్పటికే ఉన్న ఫంక్షన్‌కు ఒక ఆప్షనల్ ఆర్గ్యుమెంట్‌ను జోడించిన తర్వాత, ప్రొడక్షన్ PostgreSQL డిప్లాయ్‌మెంట్ క్రాష్ అయింది. ఈ మార్పు వల్ల ఒకే పేరుతో రెండు ఫంక్షన్‌లు మిగిలిపోయాయి, దీనివల్ల డేటాబేస్ “function is not unique” అని రిటర్న్ చేసింది మరియు API 400 ఎర్రర్‌ను ఇచ్చింది. ఒకే ఒక మైగ్రేషన్ పొరపాటు లైవ్ స్కీమాను ఎలా నిశ్శబ్దంగా దెబ్బతీస్తుందో మరియు కేవలం కోడ్-లెవల్ చెక్‌లు మాత్రమే ఎందుకు సరిపోవని ఈ సంఘటన చూపుతుంది.

What went wrong

టీమ్ ఒక స్టోర్డ్ ప్రొసీజర్‌కు అదనపు, ఆప్షనల్ పరామితిని (parameter) జోడించాల్సి వచ్చింది. పాత డెఫినిషన్‌ను ఇది ఓవర్‌రైట్ చేస్తుందని భావిస్తూ వారు CREATE OR REPLACE FUNCTION … రన్ చేశారు. ఆర్గ్యుమెంట్ లిస్ట్ పూర్తిగా సరిపోలితేనే PostgreSQL ఫంక్షన్‌ను రీప్లేస్ చేస్తుంది. సిగ్నేచర్‌ను మార్చడం వల్ల పాత దానిని అలాగే ఉంచి, సరికొత్త ఫంక్షన్ ఎంట్రీ సృష్టించబడుతుంది.

కొత్త ఆర్గ్యుమెంట్‌కు డిఫాల్ట్ వాల్యూ ఉండటం వల్ల, పాత పరామితుల సంఖ్యతో కాల్ చేసేవి రెండింటినీ మ్యాచ్ చేయగలవు. ఏ ఫంక్షన్‌ను పిలవాలో PostgreSQL నిర్ణయించలేక “function is not unique” అనే ఎర్రర్‌ను ఇచ్చింది, ఇది API నుండి 400 రెస్పాన్స్‌గా కనిపించింది.

కోడ్ రిపోజిటరీలో ఒకే డెఫినిషన్ ఉంది మరియు సోర్స్ ట్రీని స్కాన్ చేసే కస్టమ్ స్క్రిప్ట్ ఎటువంటి డూప్లికేట్‌లను చూపలేదు. ఈ డూప్లికేట్ కేవలం డేటాబేస్‌లో మాత్రమే ఉంది, సర్వర్‌పై పాత మైగ్రేషన్ ఫైల్‌ను మళ్ళీ రన్ చేసినప్పుడు ఇది ఏర్పడింది.

Why the migration slipped through

ఆప్షనల్ పరామితిని జోడించిన మైగ్రేషన్ కేవలం CREATE OR REPLACE FUNCTIONను రన్ చేసింది. మైగ్రేషన్ రెండోసారి రన్ అయినప్పుడు—బహుశా రోల్‌బ్యాక్ తర్వాత లేదా రిపీట్ డిప్లాయ్‌మెంట్ సమయంలో—డేటాబేస్ ఆ కమాండ్‌ను “ఉన్నదాన్ని రీప్లేస్ చేయండి” అని కాకుండా “కొత్త ఓవర్‌లోడ్‌ను జోడించండి” అని అర్థం చేసుకుంది. మైగ్రేషన్ దాని ఫలిత స్థితిని (resulting state) ధృవీకరించలేదు, కాబట్టి డూప్లికేట్ తెలియకుండానే ఉండిపోయింది.

రిపోజిటరీని తనిఖీ చేసిన స్క్రిప్ట్ సోర్స్ ఫైల్‌లను పరిశీలించింది, లైవ్ స్కీమాను కాదు. అది తలుపు వైపు చూస్తుండగా, బగ్ వెనుక నుండి లోపలికి వచ్చింది.

The stakes

ఒకే ఒక అస్పష్టమైన ఫంక్షన్ దానిపై ఆధారపడిన ఏ సేవనైనా నిలిపివేయగలదు. ఫంక్షన్ల సంఖ్య తప్పుగా ఉంటే ట్రాన్సాక్షన్‌ను రోల్‌బ్యాక్ చేయడం మరియు స్కీమా క్యాష్‌ను రీలోడ్ చేయమని నోటిఫై చేయడం ద్వారా దీనిని సరిదిద్దారు.

How to safeguard migrations

టీమ్ మైగ్రేషన్‌ను స్పష్టమైన చెక్‌లతో తిరిగి నిర్మించింది, దీనిని ఒక స్వయంగా ధృవీకరించుకునే (self-asserting) ఆపరేషన్‌గా మార్చారు:

  • ట్రాన్సాక్షన్‌ను ప్రారంభించండి (Start a transaction), తద్వారా ఏదైనా వైఫల్యం జరిగితే మొత్తం మార్పు రోల్‌బ్యాక్ అవుతుంది.
  • కొత్త వెర్షన్‌ను సృష్టించే ముందు పాత ఫంక్షన్‌ను స్పష్టంగా డ్రాప్ చేయండి (Drop the old function explicitly), తద్వారా ఒకే ఒక డెఫినిషన్ ఉండేలా చూడవచ్చు.
  • కావలసిన సిగ్నేచర్‌తో కొత్త ఫంక్షన్‌ను సృష్టించండి (Create the new function).
  • pg_catalogలో ఇచ్చిన పేరుతో ఉన్న ఫంక్షన్‌ల సంఖ్యను లెక్కించి, అది ఖచ్చితంగా ఒకటి అని ధృవీకరించండి (Count the functions).
  • సంఖ్యలో తేడా ఉంటే ట్రాన్సాక్షన్‌ను రోల్‌బ్యాక్ చేయండి (Roll back), తద్వారా డూప్లికేట్ అలాగే ఉండకుండా నిరోధించవచ్చు.
  • తదుపరి క్వెరీలు అప్‌డేట్ చేసిన డెఫినిషన్‌ను చూసేలా స్కీమా క్యాష్‌ను రీలోడ్ చేయమని నోటిఫై చేయండి (Notify the schema cache).

కోడ్ సరైనదని ఊహించే బదులు, డేటాబేస్‌ను “ఏ ఫంక్షన్‌లు అందుబాటులో ఉన్నాయి?” అని అడగడం ద్వారా, మైగ్రేషన్ మళ్ళీ మళ్ళీ రన్ చేసినా, పార్షియల్ డిప్లాయ్‌మెంట్‌లకైనా లేదా మాన్యువల్ ఎడిట్‌లకైనా నమ్మదగినదిగా మారుతుంది.

Counter-argument: convenience vs. safety

CREATE OR REPLACE FUNCTION అనేది డెవలపర్లు విడివిడిగా డ్రాప్ స్టేట్‌మెంట్‌లను రాయకుండా వేగంగా ఇటరేట్ చేయడానికి వీలు కల్పిస్తుంది కాబట్టి ఆకర్షణీయంగా ఉంటుంది. మైగ్రేషన్‌లు ఒకేసారి రన్ అయ్యి, మళ్ళీ ఎప్పుడూ రన్ కానటువంటి వాతావరణాలలో ఇది బాగా పనిచేస్తుంది. మైగ్రేషన్‌లు మళ్ళీ ప్లే చేయబడినప్పుడు—టెస్ట్ డేటాబేస్‌లను రీసెట్ చేసే CI పైప్‌లైన్‌లు, ఆటోమేటెడ్ రోల్‌బ్యాక్‌లు లేదా ప్రొడక్షన్‌లో మాన్యువల్ రీ-అప్లికేషన్‌ల వల్ల—రిస్క్ కనిపిస్తుంది.

Takeaway

CREATE OR REPLACEతో ఫంక్షన్ సిగ్నేచర్‌ను మార్చడం వల్ల రీప్లేస్‌మెంట్ గ్యారెంటీ ఉండదు—ఆర్గ్యుమెంట్ లిస్ట్ భిన్నంగా ఉంటే PostgreSQL నిశ్శబ్దంగా ఒక ఓవర్‌లోడ్‌ను సృష్టిస్తుంది. మైగ్రేషన్‌లపై ఆధారపడే ప్రొడక్షన్ ఎన్విరాన్‌మెంట్‌లు కేవలం సోర్స్ కోడ్‌ను మాత్రమే కాకుండా, ఫలిత స్కీమాను కూడా ధృవీకరించాలి. స్పష్టమైన డ్రాప్స్, ట్రాన్సాక్షనల్ చెక్‌లు మరియు మైగ్రేషన్ తర్వాత చేసే ధృవీకరణలను (assertions) చేర్చడం ద్వారా, ఒక సౌకర్యవంతమైన షార్ట్‌కట్‌ను నమ్మదగిన, పునరావృతమయ్యే ప్రక్రియగా మార్చవచ్చు.