CRM ನಲ್ಲಿ ಇಪ್ಪತ್ತು ಸಂಪರ್ಕಗಳನ್ನು (contacts) ಆರ್ಕೈವ್ ಮಾಡಬೇಕಿತ್ತು, ಆದರೆ UI ಹಸಿರು ಯಶಸ್ಸಿನ ಬ್ಯಾಡ್ಜ್ ಅನ್ನು ತೋರಿಸಿತು ಮತ್ತು ಆ ಪ್ರಕ್ರಿಯೆಯು ಯಾವುದೇ ಸೂಚನೆ ಇಲ್ಲದೆ ಏನನ್ನೂ ಮಾಡಲಿಲ್ಲ. Supabase-JS ಮ್ಯುಟೇಶನ್‌ಗಳಲ್ಲಿ (mutations) error ಫೀಲ್ಡ್ ಅನ್ನು ಕಡ್ಡಾಯಗೊಳಿಸುವ ಒಂದು TypeScript ಹೆಲ್ಪರ್, ಈಗ ಅಂತಹ ವೈಫಲ್ಯಗಳನ್ನು ಮುಚ್ಚಿಡುವ ಬದಲು ಅವುಗಳನ್ನು ಎದುರಿಸಲು ಡೆವಲಪರ್‌ಗಳನ್ನು ಒತ್ತಾಯಿಸುತ್ತದೆ.

Supabase-JS ನ ರಿಟರ್ನ್ ಶೇಪ್ (return shape) ಏಕೆ ಒಂದು ಬಲೆ?

ಡೇಟಾಬೇಸ್ ಬರವಣಿಗೆಯು (database write) ತಿರಸ್ಕರಿಸಲ್ಪಟ್ಟಾಗ Supabase ನ JavaScript ಕ್ಲೈಂಟ್ (@supabase/supabase-js) ಎಕ್ಸೆಪ್ಶನ್‌ಗಳನ್ನು (exceptions) ಎಸೆಯುವುದಿಲ್ಲ. ಬದಲಾಗಿ, ಅದು { data, error } ಎಂಬ ಆಬ್ಜೆಕ್ಟ್‌ನೊಂದಿಗೆ ಪ್ರಾಮಿಸ್ ಅನ್ನು (promise) ರೆಸಲ್ವ್ ಮಾಡುತ್ತದೆ. ಒಂದು ವೇಳೆ row-level security (RLS) ಪಾಲಿಸಿ, unique-key ಉಲ್ಲಂಘನೆ ಅಥವಾ ಯಾವುದೇ ಇತರ ನಿರ್ಬಂಧವು ಕ್ವೇರಿಯನ್ನು ತಡೆದರೆ, data ಎಂಬುದು null ಆಗಿ ಬರುತ್ತದೆ ಮತ್ತು error ನಲ್ಲಿ ಡೇಟಾಬೇಸ್ ಸಂದೇಶವಿರುತ್ತದೆ. ಕರೆಯುವವರು (caller) error ಅನ್ನು ಪರಿಶೀಲಿಸುತ್ತಾರೆ ಎಂದು ಕ್ಲೈಂಟ್ ಭಾವಿಸುತ್ತದೆ; ಅದು ಎಂದಿಗೂ ಕರೆಯನ್ನು ರದ್ದುಗೊಳಿಸುವುದಿಲ್ಲ.

ಪ್ರಾಯೋಗಿಕವಾಗಿ ಅನೇಕ ಕೋಡ್‌ಬೇಸ್‌ಗಳು ಈ ಕರೆಯನ್ನು 'ಫೈರ್-ಅಂಡ್-ಫಾರ್ಗೆಟ್' (fire-and-forget) ಕಾರ್ಯಾಚರಣೆಯಾಗಿ ಪರಿಗಣಿಸುತ್ತವೆ:

await supabase
  .from('contacts')
  .update({ statut: 'ancien', archived_at: now })
  .eq('id', id)

return { ok: true }

update ಅನ್ನು RLS ನಿಯಮವು ತಡೆದಾಗಲೂ, ಪ್ರಾಮಿಸ್ ರೆಸಲ್ವ್ ಆಗುತ್ತದೆ. ಡೆವಲಪರ್ ಎಂದಿಗೂ { error } ಅನ್ನು ಡಿಸ್ಟ್ರಕ್ಚರ್ (destructure) ಮಾಡದ ಕಾರಣ, ವೈಫಲ್ಯವು ಅದೃಶ್ಯವಾಗಿರುತ್ತದೆ. ಫಂಕ್ಷನ್ { ok: true } ಅನ್ನು ರಿಟರ್ನ್ ಮಾಡುತ್ತದೆ, UI ಯಶಸ್ಸನ್ನು ತೋರಿಸುತ್ತದೆ ಮತ್ತು ಡೇಟಾ ಬದಲಾಗದೆ ಉಳಿಯುತ್ತದೆ. ಯಾವುದೇ ಲಾಗ್‌ಗಳು (logs) ಕಾಣಿಸಿಕೊಳ್ಳುವುದಿಲ್ಲ, ಯಾವುದೇ Sentry ಅಲರ್ಟ್ ಬರುವುದಿಲ್ಲ ಮತ್ತು ಆ ಬಗ್ (bug) ದಿನಗಟ್ಟಲೆ ಹಾಗೆಯೇ ಇರಬಹುದು.

ಲಿಂಟರ್ (linter) ಸಾಕಾಗುವುದಿಲ್ಲ

ಸ್ಟ್ಯಾಟಿಕ್ ಅನಾಲಿಸಿಸ್ ಟೂಲ್‌ಗಳು (Static analysis tools) error ಪ್ರಾಪರ್ಟಿಯನ್ನು ನಿರ್ಲಕ್ಷಿಸಿದಾಗ ಎಚ್ಚರಿಸಬಹುದು, ಆದರೆ ಅವು ರನ್‌ಟೈಮ್ ಕಾಂಟ್ರಾಕ್ಟ್ ಅನ್ನು (runtime contract) ಜಾರಿಗೊಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಒಬ್ಬ ಡೆವಲಪರ್ ಇನ್ನೂ const _ = await … ಎಂದು ಬರೆದು ಎಚ್ಚರಿಕೆಯನ್ನು ನಿರ್ಲಕ್ಷಿಸಬಹುದು ಅಥವಾ ನಿಯಮವನ್ನು ನಿರ್ಲಕ್ಷಿಸಲು ಕಾಮೆಂಟ್ ಸೇರಿಸಬಹುದು. ಮೂಲಭೂತ ಸಮಸ್ಯೆ ಏನೆಂದರೆ, ಟೈಪ್ ಸಿಸ್ಟಮ್ (type system) error ಬಗ್ಗೆ ಉಲ್ಲೇಖಿಸದೆಯೇ ಕರೆಯು ಯಶಸ್ವಿಯಾಗಲು ಅನುಮತಿಸುತ್ತದೆ.

mutate() ಹೆಲ್ಪರ್: ಎರರ್ ಹ್ಯಾಂಡ್ಲಿಂಗ್ ಅನ್ನು ಕಡ್ಡಾಯಗೊಳಿಸುವುದು

ಲೇಖಕರು ರಿಟರ್ನ್ ಟೈಪ್‌ನ ಶೇಪ್ ಅನ್ನು ಬದಲಾಯಿಸುವ mutate() ಎಂಬ ಸಣ್ಣ ವ್ರಾಪ್ಪರ್ (wrapper) ಅನ್ನು ನಿರ್ಮಿಸಿದ್ದಾರೆ. { data, error } ಬದಲಿಗೆ, ಈ ಹೆಲ್ಪರ್ [data, error] ಎಂಬ ಟ್ಯುಪಲ್ ಅನ್ನು (tuple) ರಿಟರ್ನ್ ಮಾಡುತ್ತದೆ, ಇಲ್ಲಿ error ಒಂದು ಕಡ್ಡಾಯ ಫೀಲ್ಡ್ ಆಗಿದೆ. TypeScript ನಂತರ ಎರಡನೇ ಎಲಿಮೆಂಟ್ ಅನ್ನು ಬಿಟ್ಟುಬಿಡುವ ಯಾವುದೇ ಕರೆಯನ್ನು ಕಾಂಪೈಲ್ ಮಾಡಲು ನಿರಾಕರಿಸುತ್ತದೆ.

async function mutate<T>(promise: Promise<{ data: T | null; error: any }>) {
  const { data, error } = await promise
  // Send error to Sentry immediately
  if (error) Sentry.captureException(error)
  return [data, error] as const
}

ಬಳಕೆ ಈಗ ಸ್ಪಷ್ಟವಾಗಿರುತ್ತದೆ:

const [result, err] = await mutate(
  supabase
    .from('contacts')
    .update({ statut: 'ancien', archived_at: now })
    .eq('id', id)
)

if (err) {
  // Handle or rethrow
  return { ok: false, message: err.message }
}
return { ok: true, data: result }

ಡೆವಲಪರ್ err ಅನ್ನು ಕ್ಯಾಪ್ಚರ್ ಮಾಡಲು ಮರೆತರೆ, TypeScript ಈ ಎರರ್ ಅನ್ನು ನೀಡುತ್ತದೆ: “Tuple type [T, any] of length 2 has no element at index 1.” ಈ ಸಮಸ್ಯೆಯನ್ನು ಬಗೆಹರಿಸುವವರೆಗೆ ಕೋಡ್ ಕಾಂಪೈಲ್ ಆಗುವುದಿಲ್ಲ. ಈ ಹೆಲ್ಪರ್ Sentry ಇನ್ಸ್ಟ್ರುಮೆಂಟೇಶನ್ ಅನ್ನು (instrumentation) ಕೂಡ ಸೇರಿಸುತ್ತದೆ, ಇದರಿಂದ ಕರೆಯುವವರು ನಂತರ ಅದನ್ನು ನಿರ್ಲಕ್ಷಿಸಿದರೂ ಸಹ ಪ್ರತಿಯೊಂದು ಡೇಟಾಬೇಸ್ ತಿರಸ್ಕಾರವು ಲಾಗ್ ಆಗುವುದನ್ನು ಇದು ಖಚಿತಪಡಿಸುತ್ತದೆ.

ಅಪಾಯದಲ್ಲಿ ಏನಿದೆ?

  • ಡೇಟಾ ಸಮಗ್ರತೆ (Data integrity) – ಮೌನ ವೈಫಲ್ಯಗಳು (Silent failures) ಅಮಾನ್ಯ ಸ್ಥಿತಿಯನ್ನು (invalid state) ಪ್ರೊಡಕ್ಷನ್‌ಗೆ ತರಲು ಬಿಡುತ್ತವೆ. ಸಕ್ರಿಯ ಪಟ್ಟಿಯಿಂದ (active list) ಎಂದಿಗೂ ಹೊರಬರದ ಆರ್ಕೈವ್ ಮಾಡಿದ ಸಂಪರ್ಕವು ಮುಂದಿನ ವರದಿಗಳಲ್ಲಿ ತಪ್ಪುಗಳಿಗೆ ಕಾರಣವಾಗಬಹುದು.
  • ಬಳಕೆದಾರರ ನಂಬಿಕೆ (User trust) – ಏನೂ ಬದಲಾಗದಿದ್ದರೂ ಯಶಸ್ಸನ್ನು ತೋರಿಸುವ UI ಬಳಕೆದಾರರ ವಿಶ್ವಾಸವನ್ನು ಕುಗ್ಗಿಸುತ್ತದೆ. ಗ್ರಾಹಕರು "ಆರ್ಕೈವ್" ಆಗಿದೆ ಎಂದು ನೋಡುತ್ತಾರೆ ಆದರೆ ಹುಡುಕಾಟದಲ್ಲಿ (searches) ಇನ್ನೂ ಅದೇ ಸಂಪರ್ಕವನ್ನು ಕಾಣುತ್ತಾರೆ.
  • ಡೆವಲಪರ್ ಸಮಯ (Developer time) – ಕಾಲ್ಪನಿಕ ಬಗ್‌ಗಳನ್ನು (phantom bugs) ಹುಡುಕಲು ಗಂಟೆಗಟ್ಟಲೆ ಸಮಯ ವ್ಯಯವಾಗುತ್ತದೆ. ಸ್ಪಷ್ಟವಾದ ಎರರ್ ಹ್ಯಾಂಡ್ಲಿಂಗ್ ವೈಫಲ್ಯ ಸಂಭವಿಸಿದ ಸ್ಥಳದಲ್ಲೇ ಸಮಸ್ಯೆಯನ್ನು ಎತ್ತಿ ತೋರಿಸುತ್ತದೆ, ಇದರಿಂದ ಡಿಬಗ್ಗಿಂಗ್ ಪ್ರಕ್ರಿಯೆಯು ಸುಲಭವಾಗುತ್ತದೆ.
  • ಕಾರ್ಯಾಚರಣೆಯ ವೆಚ್ಚ (Operational cost) – ಮೌನವಾಗಿ ಡೇಟಾ ಕಳೆದುಹೋಗುವ ಘಟನೆಯ ವೆಚ್ಚಕ್ಕೆ ಹೋಲಿಸಿದರೆ, ಕೆಲವು ಹೆಚ್ಚುವರಿ ಕೋಡ್ ಸಾಲುಗಳು ಮತ್ತು ಸಣ್ಣ ವ್ರಾಪ್ಪರ್ ಅನ್ನು ಸೇರಿಸುವುದು ಅತ್ಯಲ್ಪವೇ ಆಗಿದೆ.

ಲಾಭ ಮತ್ತು ನಷ್ಟದ ಸಮತೋಲನ (The trade-off)

ಈ ಹೆಲ್ಪರ್ ಕೋಡ್‌ನ ಉದ್ದವನ್ನು (verbosity) ಹೆಚ್ಚಿಸುತ್ತದೆ: ಪ್ರತಿಯೊಂದು ಮ್ಯುಟೇಶನ್ ಕರೆಯು ಈಗ ಟ್ಯುಪಲ್ ಅನ್ನು ರಿಟರ್ನ್ ಮಾಡುತ್ತದೆ ಮತ್ತು ಕರೆಯುವವರು if (err) ಬ್ಲಾಕ್ ಅನ್ನು ಬರೆಯಲೇಬೇಕು. ಕೆಲವು ತಂಡಗಳು ಇದನ್ನು ಬಾಯಲ್‌ಪ್ಲೇಟ್ ನಾಯ್ಸ್ (boilerplate noise) ಎಂದು ಪರಿಗಣಿಸಬಹುದು, ವಿಶೇಷವಾಗಿ ಯಶಸ್ಸನ್ನು ನಿರೀಕ್ಷಿಸುವ ಸರಳ CRUD ಕ್ರಿಯೆಗಳಿಗಾಗಿ. ಆದರೆ, ಈ ಹೆಚ್ಚುವರಿ ಕೋಡ್ ಒಂದು ಸುರಕ್ಷತಾ ಕ್ರಮವೇ ಹೊರತು ಐಚ್ಛಿಕ ಫೀಚರ್ ಅಲ್ಲ ಎಂಬುದು ಇದಕ್ಕೆ ಪ್ರತಿಯಾಗಿ ನೀಡುವ ವಾದವಾಗಿದೆ. ಡೇಟಾ ನಿಖರತೆ ಅತ್ಯಗತ್ಯವಾಗಿರುವ ವಾತಾವರಣಗಳಲ್ಲಿ—CRM ಸಿಸ್ಟಮ್‌ಗಳು, ಹಣಕಾಸು, ಆರೋಗ್ಯ—ಈ ಪರಿಶೀಲನೆಯನ್ನು ಕಡ್ಡಾಯಗೊಳಿಸುವುದು ಅತ್ಯಂತ ಪ್ರಯೋಜನಕಾರಿ.

ಮುಂದೆ ಏನು?

ಯಾವುದೇ ವಿವರಣೆಯಿಲ್ಲದೆ ಶೂನ್ಯ ರೋಗಳನ್ನು (zero rows) ರಿಟರ್ನ್ ಮಾಡುವ RLS ಪಾಲಿಸಿಗಳನ್ನು ಪರಿಶೀಲಿಸುವ ಮೂರನೇ ಭಾಗವನ್ನು ಲೇಖಕರು ಭರವಸೆ ನೀಡಿದ್ದಾರೆ. ಆ ಮಾದರಿಯು, ಮೌನ-ಎರರ್ ಪ್ರಕರಣದಂತೆಯೇ, ಯಶಸ್ವಿ ಕ್ವೇರಿಯ ಹಿಂದೆ ವೈಫಲ್ಯಗಳನ್ನು ಮರೆಮಾಚುತ್ತದೆ. ಈ ಸರಣಿಯು Supabase API ನ "ಅಫವೋಹದ" (rumor) ಭಾಗವನ್ನು ಬಯಲಿಗೆಳೆಯುವ ಮತ್ತು ಡೆವಲಪರ್‌ಗಳಿಗೆ ಸತ್ಯವನ್ನು ತಿಳಿಯಲು ನಿರ್ದಿಷ್ಟ ಪರಿಕರಗಳನ್ನು ನೀಡುವ ಗುರಿಯನ್ನು ಹೊಂದಿದೆ.

ಸಾರಾಂಶ (Takeaway): ನೀವು error ಫೀಲ್ಡ್ ಅನ್ನು ಓದಲು ನೆನಪಿಸಿಕೊಂಡರೆ ಹೊರತು, Supabase-JS ನ ವಿನ್ಯಾಸವು ವಿಫಲವಾದ ಬರವಣಿಗೆಯನ್ನು ಯಶಸ್ಸಿನಂತೆ ಕಾಣುವಂತೆ ಮಾಡುತ್ತದೆ. error ಅನ್ನು ಕಡ್ಡಾಯಗೊಳಿಸುವ ಮತ್ತು ಅದನ್ನು Sentry ಗೆ ಲಾಗ್ ಮಾಡುವ TypeScript-ಬಲಪಡಿಸಿದ ಹೆಲ್ಪರ್ ಮೂಲಕ ಕರೆಯಗಳನ್ನು ವ್ರಾಪ್ ಮಾಡುವ ಮೂಲಕ, ನೀವು ಮೌನ ವೈಫಲ್ಯಗಳನ್ನು ದೃಶ್ಯ ಮತ್ತು ಕಾರ್ಯಗತಗೊಳಿಸಬಹುದಾದ ಘಟನೆಗಳನ್ನಾಗಿ ಬದಲಾಯಿಸಬಹುದು. ಕೋಡ್ ಗಾತ್ರದಲ್ಲಿನ ಸಣ್ಣ ಹೆಚ್ಚಳವು ನಿಮಗೆ ಡೇಟಾ ವಿಶ್ವಾಸಾರ್ಹತೆ ಮತ್ತು ಬಳಕೆದಾರರ ನಂಬಿಕೆಯನ್ನು ನೀಡುತ್ತದೆ—ಯಾವುದೇ ಮೌನ ಯಶಸ್ಸು ಎಂದಿಗೂ ನೀಡಲಾಗದ ಎರಡು ವಿಷಯಗಳಿವು.