Skip to content
··5 मिनट पढ़ने का समय

3 मिनट से 500ms तक: वह Signup Bug जो कोई समझ में नहीं आया

मैंने एक 3-मिनट signup delay track किया जो निकला Schrödinger's user — database replication lag की वजह से writes और reads के बीच एक साथ exist करना और न करना।

आपको वह feeling पता है जब users एक ऐसा bug report करते हैं जो absolutely कोई sense नहीं बनाता? "Sign up करने के बाद app load होने में 3 मिनट लगते हैं।" तीन मिनट? वह loading time नहीं है, वह coffee break है। यह DIALØGUE के history के सबसे weird bugs में से एक को कैसे track किया इसकी कहानी है।

Mystery शुरू होती है

यह innocently enough शुरू हुई। एक new user ने Google SSO का उपयोग करके sign up किया, DIALØGUE try करने के लिए excited। फिर... कुछ नहीं। Well, exactly कुछ नहीं नहीं — उन्हें हमारा beautifully designed loading skeleton मिला। तीन पूरे मिनट के लिए।

Weird part? यह सिर्फ new users के साथ हुआ। Existing users instantly log in कर सकते थे। और यह consistent नहीं था — कभी-कभी 1 मिनट, कभी-कभी 3, कभी-कभी immediately काम करता।

मेरा पहला विचार: "Cold start issue होगी।" (Narrator: यह cold start issue नहीं थी।)

Investigation

Round 1: Frontend को Blame करो

```typescript
// First suspect: Profile loading hook
useEffect(() => \{
  if (user) {
    fetchUserProfile(); // यह forever ले रहा था
  \}
}, [user]);
```

हर जगह timers जोड़े। API call वाकई 3 मिनट ले रहा था। लेकिन क्यों? Backend को या तो data return करना चाहिए या error out करना — बस... wait नहीं करना।

Round 2: Backend को Blame करो

Supabase Edge Functions में गया:

```typescript
// User profile के लिए Edge Function
const \{ data: profile \} = await supabase
  .from('users')
  .select('*')
  .eq('id', userId)
  .single();

if (!profile) \{
  // New user - profile बनाओ
  await createUserProfile(userId);
\}
```

यह ठीक लगा। Quick होना चाहिए, है ना? और logging जोड़ने का time।

Round 3: Plot Thickens

हर जगह logs जोड़ने के बाद (और मेरा मतलब हर जगह), मैंने कुछ bizarre discover किया:

[00:00] User Google से sign in करता है
[00:01] Auth trigger fires - user record बनाता है
[00:01] Frontend profile request करता है
[00:01] Edge Function user के लिए query करता है... कोई RESULT नहीं
[00:02] Edge Function user बनाने की कोशिश करता है...
[00:02] Database constraint error: User already exists
[00:03] Function retry करता है...
[03:00] Function finally timeout करता है

रुको, क्या? User exist नहीं करता, लेकिन already exist भी करता है? Schrödinger's user? T.T

Revelation

Database logs को तब तक घूरते रहने के बाद जब तक आँखें दुखने लगीं, मैंने finally देखा। हमारे database में competing processes थे:

  1. Supabase Auth Trigger: Signup पर user record बनाता है
  2. Edge Function: अगर नहीं मिला तो user बनाने की कोशिश करता है
  3. Database Replication Lag: Trigger का INSERT अभी read replica पर replicate नहीं हुआ था

यह हो रहा था:

-- Auth trigger (primary database पर)
INSERT INTO users (id, email) VALUES ($1, $2);

-- Edge Function (replica से read करते हुए)
SELECT * FROM users WHERE id = $1; -- कुछ Return नहीं होता!

-- Edge Function (help करने की कोशिश)
INSERT INTO users (id, email) VALUES ($1, $2); -- CONFLICT!

Function exponential backoff के साथ retry करता, हर attempt same race condition से टकराता जब तक या तो:

  • Replication finally catch up (1-3 मिनट)
  • Function timeout (3 मिनट)

Update: Real Culprit और Final, Robust Solution

Initial post के बाद, हम debugging जारी रखते रहे, और जबकि हमारे backend changes improvements थे, mystery की root बेहद elusive रही। Breakthrough तब आई जब हमने focus backend से client-side hydration और authentication flow पर shift किया।

Real Culprit: एक Client-Side Race Condition

Problem slow database trigger या cold Edge Function नहीं थी। True issue एक classic client-side race condition थी:

  1. OAuth Redirect: एक new user Google से sign in करता है और हमारे app पर वापस redirect होता है।
  2. Async Session: Supabase client library (supabase-js) session establish करने के लिए URL से token process करना शुरू करती है। यह एक asynchronous process है।
  3. Premature Render: हमारी React app, हालाँकि, immediately render होती है। यह step 2 से async process complete होने से पहले user के session के लिए पूछती है।
  4. Failure: App को null session मिलती है, conclude करती है user logged in नहीं है, और blank या error state render करती है। कुछ moments बाद, session available हो जाती है, लेकिन बहुत देर हो चुकी — UI already अपना decision ले चुकी है।

हमारे initial workarounds, जैसे client-side retries जोड़ना, इस fundamental race condition से लड़ने के symptoms थे।

Solution: Authentication के लिए एक Single Source of Truth

सही और final solution था हमारे frontend authentication state management को truly event-driven और robust बनाने के लिए re-architect करना।

1. SupabaseProvider में Centralized Logic: हमने अपने SupabaseProvider को authentication के लिए single, authoritative source of truth बनाया। हमने अन्य hooks से सभी other listeners और checks हटाए।

2. onAuthStateChange को Correctly Use करना: Fix का core Supabase के onAuthStateChange listener पर exclusively rely करना था।

// SupabaseProvider.tsx में Simplified logic

export function SupabaseProvider(\{ children \}) {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true); // Loading state में शुरू करें

  useEffect(() => {
    const { data: { subscription } } = supabase.auth.onAuthStateChange(
      (event, session) => \{
        setUser(session?.user ?? null);
        // हम authentication को "finished" तभी मानते हैं जब यह listener fire करे।
        setLoading(false);
      \}
    );

    return () => subscription.unsubscribe();
  }, []);

  // ...
}

यह pattern ensure करता है कि पूरा application loading state में रहे जब तक Supabase confirm न करे कि user का session valid है या null है। अब कोई race condition नहीं।

Happy Ending

DIALØGUE अब नए users को एक second से कम में onboard करता है। Signup के दौरान अब कोई coffee break नहीं। कोई confused users नहीं जो सोचें कि उन्होंने कुछ तोड़ा।

Fix 3 हफ्तों से production में है। Zero timeout issues। Zero race conditions। बस smooth, fast signups जैसे शुरुआत से होना चाहिए था।

क्या इस bug को debug करने में एक हफ्ता खर्च करना worth it था? जब मैं new users को sign up करने के कुछ minutes के भीतर seamlessly अपना पहला podcast बनाते देखता हूँ — बिल्कुल। :D

क्या आपने कभी ऐसा bug track किया जहाँ चीज़ एक साथ exist करती थी और नहीं भी? मुझे लगता है हर developer के पास कम से कम एक Schrödinger's bug story है। मुझे आपकी सुनाइए!

शुभकामनाओं सहित,

Chandler

अब speedy signup try करना चाहते हैं? DIALØGUE पर अपना AI podcast बनाएं। मैं promise करता हूँ यह अब 3 मिनट नहीं लेगा :)

पढ़ना जारी रखें

मेरा सफ़र
जुड़ें
भाषा
सेटिंग्स