Skip to content

[wip] redis support for multiplayer prompting #665

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 11 commits into
base: main
Choose a base branch
from

Conversation

vcashwin
Copy link
Contributor

@vcashwin vcashwin commented May 21, 2025

PR Type

Enhancement, Documentation, Configuration changes, Dependencies


Description

  • Integrate Redis for prompt stream storage

  • Refactor API to use Redis endpoints

  • Update frontend hooks and components

  • Add Redis config, env vars, dependencies


Changes walkthrough 📝

Relevant files
Enhancement
8 files
MultiplayerHomepage.tsx
Refactor homepage to use Redis prompts                                     
+8/-41   
route.ts
Implement Redis-based prompt rotation endpoint                     
+38/-34 
route.ts
Add poll route with Redis init logic                                         
+54/-0   
route.ts
Refactor prompts API to push to Redis                                       
+33/-89 
PromptDisplay.tsx
Rewrite PromptDisplay for Redis prompts                                   
+78/-318
PromptPanel.tsx
Update PromptPanel to use new prompts prop                             
+9/-20   
usePrivy.ts
Force mock Privy in development                                                   
+1/-3     
usePromptsApi.ts
Rewrite prompts hook for Redis endpoints                                 
+48/-119
Miscellaneous
1 files
store.ts
Export applyPromptToStream from store                                       
+1/-1     
Formatting
1 files
HeroSection.tsx
Remove unused prompt props                                                             
+0/-4     
Dependencies
3 files
redis.ts
Add Redis client setup                                                                     
+7/-0     
package.json
Add @upstash/redis dependency                                                       
+1/-0     
pnpm-lock.yaml
Update lockfile with Redis entries                                             
+47/-31 
Configuration changes
2 files
serverEnv.ts
Include Redis config in environment                                           
+12/-0   
turbo.json
Add Redis env to turbo config                                                       
+3/-1     
Documentation
1 files
.env.example
Define Redis env variables example                                             
+4/-1     

Need help?
  • Type /help how to ... in the comments thread for any questions about PR-Agent usage.
  • Check out the documentation for more information.
  • Copy link

    vercel bot commented May 21, 2025

    The latest updates on your projects. Learn more about Vercel for Git ↗︎

    Name Status Preview Comments Updated (UTC)
    pipelines-app ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 21, 2025 6:59am

    Copy link

    PR Reviewer Guide 🔍

    Here are some key observations to aid the review process:

    ⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
    🧪 No relevant tests
    🔒 No security concerns identified
    ⚡ Recommended focus areas for review

    Modulo logic

    The calculation const nextIndex = (currentIndex - 1) % prompts.length can yield negative indices when currentIndex is 0. It should adjust by adding prompts.length before applying modulo to ensure a valid wrap-around.

      // Rotate to next in the top 20 which is the previous index, add modulo correctly
      const nextIndex = (currentIndex - 1) % prompts.length;
      newActiveId = prompts[nextIndex].id;
      newActivePrompt = prompts[nextIndex].content;
    }
    Hardcoded mock

    The shouldMock flag is unconditionally set to true, bypassing real authentication in production. Consider deriving it from environment variables to avoid shipping mocks in production builds.

    const shouldMock = true;
    
    export const usePrivy = shouldMock
      ? () => mockPrivy as unknown as PrivyInterface
      : _usePrivy;
    Payload validation

    The POST handler accepts request JSON without validating types for content and id. Consider adding schema validation to prevent malformed or malicious payloads.

    const body = await req.json();
    const { content, id } = body;
    
    if (!content) {
      return NextResponse.json({ error: "Missing 'content'" }, { status: 400 });
    }

    Copy link

    PR Code Suggestions ✨

    Explore these optional code suggestions:

    CategorySuggestion                                                                                                                                    Impact
    Possible issue
    Revert unconditional auth mocking

    The usePrivy hook is now unconditionally mocking authentication in all environments,
    including production. Restore the original environment-based condition to avoid
    using mock credentials in production.

    apps/app/hooks/usePrivy.ts [27]

    -const shouldMock = true;
    +const shouldMock =
    +  process.env.NEXT_PUBLIC_USE_PRIVY_MOCK === "true" &&
    +  process.env.NODE_ENV === "development";
    Suggestion importance[1-10]: 10

    __

    Why: Forcing shouldMock = true mocks out authentication in production, exposing a security risk by bypassing real auth flows.

    High
    Parse Redis list items as objects

    The Redis lrange method returns raw JSON strings, so you need to parse each entry
    into a MultiplayerPrompt object before accessing its properties. Without parsing,
    operations like findIndex will fail at runtime.

    apps/app/app/api/cron/process-queue/route.ts [8]

    -const prompts = await redis.lrange<MultiplayerPrompt>("prompt:stream", 0, -1);
    +const raw = await redis.lrange<string>("prompt:stream", 0, -1);
    +const prompts = raw.map(item => JSON.parse(item) as MultiplayerPrompt);
    Suggestion importance[1-10]: 9

    __

    Why: Without JSON parsing, prompts is an array of strings, causing findIndex and property access on p.id to fail at runtime.

    High
    Convert raw Redis entries to objects

    Similar to the queue processing route, lrange returns stringified JSON. You should
    map and JSON.parse each entry to a MultiplayerPrompt before returning them. This
    prevents downstream code from working with raw strings instead of prompt objects.

    apps/app/app/api/prompts/poll/route.ts [32-36]

    -const prompts = await redis.lrange<MultiplayerPrompt>(
    -  "prompt:stream",
    -  0,
    -  -1,
    -);
    +const raw = await redis.lrange<string>("prompt:stream", 0, -1);
    +const prompts = raw.map(item => JSON.parse(item) as MultiplayerPrompt);
    Suggestion importance[1-10]: 9

    __

    Why: The lrange result are raw strings; parsing is required to return valid MultiplayerPrompt objects to downstream consumers.

    High
    Check response status before parsing

    You should verify res.ok before calling res.json() to handle HTTP errors explicitly
    and avoid parsing invalid responses. Throw or handle errors when the response is not
    successful.

    apps/app/hooks/usePromptsApi.ts [24-30]

     const res = await fetch("/api/prompts", {
       method: "POST",
       body: JSON.stringify(newPrompt),
       headers: { "Content-Type": "application/json" },
     });
    +if (!res.ok) {
    +  throw new Error(`Failed to submit prompt: ${res.statusText}`);
    +}
     const data = await res.json();
    Suggestion importance[1-10]: 6

    __

    Why: Adding a res.ok check prevents attempting to parse error responses and improves error handling without being critical to core functionality.

    Low

    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Projects
    None yet
    Development

    Successfully merging this pull request may close these issues.

    1 participant