Skip to main content
CodePlanet Docs

Data Flow

How data moves through the system

Understanding how data moves through CodePlanet helps you use the platform effectively and debug issues.

Request Lifecycle

Here's how a typical user action flows through the system:

┌─────────────────────────────────────────────────────────────────────────────┐
│                             User Action                                      │
│                          (Click, Type, Submit)                               │
└─────────────────────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────────────────┐
│                           React Component                                    │
│   • Captures user input                                                      │
│   • Updates local state (useState)                                          │
│   • Triggers API call                                                        │
└─────────────────────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────────────────┐
│                            API Route                                         │
│   1. Authenticate (JWT verification)                                        │
│   2. Validate input (schema check)                                          │
│   3. Check rate limits                                                       │
│   4. Execute business logic                                                  │
└─────────────────────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────────────────┐
│                             Supabase                                         │
│   • RLS checks user permissions                                             │
│   • Executes SQL query                                                       │
│   • Returns result                                                           │
└─────────────────────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────────────────┐
│                            Response                                          │
│   • JSON payload returned                                                    │
│   • React state updated                                                      │
│   • UI re-renders                                                            │
└─────────────────────────────────────────────────────────────────────────────┘

Example: Submitting a Solution

Let's trace a complete solution submission:

1. User Clicks "Submit"

// Client component
async function handleSubmit() {
  setLoading(true);
  
  const response = await fetch("/api/v1/problems/two-sum/submit", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ language: "python", code }),
  });
  
  const result = await response.json();
  setResult(result);
}

2. API Route Processes Request

// /api/v1/problems/[slug]/submit/route.ts
export async function POST(request: Request, { params }) {
  // 1. Get authenticated user
  const supabase = await createClient();
  const { data: { user } } = await supabase.auth.getUser();
  
  // 2. Validate input
  const { language, code } = await request.json();
  if (!SUPPORTED_LANGUAGES.includes(language)) {
    return Response.json({ error: "Invalid language" }, { status: 400 });
  }
  
  // 3. Run code (external service)
  const result = await runCode(code, language, testCases);
  
  // 4. Save submission
  await supabase.from("submissions").insert({
    user_id: user.id,
    problem_slug: params.slug,
    language,
    code,
    status: result.status,
  });
  
  // 5. Update topic performance
  await updateTopicPerformance(user.id, topics, result.success);
  
  return Response.json({ success: true, data: result });
}

3. Database Operations

-- Insert submission
INSERT INTO submissions (user_id, problem_slug, language, code, status)
VALUES ($1, $2, $3, $4, $5);
 
-- Update topic performance (trigger)
UPDATE topic_performance
SET total_attempts = total_attempts + 1,
    correct_attempts = correct_attempts + $2::int,
    weakness_score = calculate_weakness(...)
WHERE user_id = $1 AND topic = $3;

4. Response Returned

{
  "success": true,
  "data": {
    "submission_id": "sub_abc123",
    "status": "accepted",
    "runtime": "45 ms",
    "memory": "16.2 MB",
    "testCases": { "passed": 57, "total": 57 }
  }
}

State Management

Server State (Database)

  • Source of truth for all persistent data
  • Protected by RLS policies
  • Accessed via Supabase client

Client State (React)

Local State (useState):

const [isLoading, setIsLoading] = useState(false);

URL State (searchParams):

const searchParams = useSearchParams();
const difficulty = searchParams.get("difficulty");

Context (shared state):

const { user, subscription } = useAuth();

Caching Strategy

Server-Side

  • Static pages cached at CDN edge
  • API responses cached with appropriate headers
  • Database queries cached with prepared statements

Client-Side

  • React Query/SWR for API caching (where used)
  • Local storage for preferences
  • Session storage for temporary data

Real-Time Updates

Some features use real-time subscriptions:

// Subscribe to submission updates
supabase
  .channel("submissions")
  .on("postgres_changes", {
    event: "UPDATE",
    schema: "public",
    table: "submissions",
    filter: `id=eq.${submissionId}`,
  }, (payload) => {
    setSubmission(payload.new);
  })
  .subscribe();

Error Propagation

Errors flow up through the stack:

Database Error → API catches → Returns error response → Client displays

Logged to monitoring

Error Response Format

{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid input provided",
    "details": { "field": "code", "reason": "Cannot be empty" }
  }
}

Optimistic Updates

For better UX, some actions update UI before server confirmation:

// Optimistic update
setProblems(prev => 
  prev.map(p => p.id === id ? { ...p, status: "solved" } : p)
);
 
// Then sync with server
try {
  await submitSolution(id, code);
} catch (error) {
  // Rollback on failure
  setProblems(prev => 
    prev.map(p => p.id === id ? { ...p, status: "unsolved" } : p)
  );
}

Webhook Flow

External events (like payments) use webhooks:

┌────────────┐     ┌──────────────┐     ┌─────────────┐
│  Razorpay  │────▶│   Webhook    │────▶│  Database   │
│  Payment   │     │   Endpoint   │     │   Update    │
└────────────┘     └──────────────┘     └─────────────┘


                   ┌──────────────┐
                   │    User      │
                   │ Notification │
                   └──────────────┘

Next Steps