QueueLab / QueueLab/QCX

Asynchronous Report Generation

Open
#660 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
19
Forks
7
Avg merge
59m
Merged PRs (30d)
16

Description

I understand you want to make report generation asynchronous so users can interact with other parts of the system while reports are being generated. Currently, the submit server action in app/actions.tsx processes requests synchronously, blocking until all agent work completes before returning 1 .

Current Blocking Behavior

The system uses streaming primitives for progressive UI rendering, but the server action itself is synchronous:

  • The submit function initializes streaming state but waits for all processing to complete 1
  • The researcher agent runs in a synchronous loop until a non-empty response is generated 2
  • Resolution search processing is called synchronously 3
  • The function only returns after all work is done 4

Required Changes for Asynchronous Processing

To make report generation truly asynchronous, you would need to implement a background job queue system:

1. Job Queue Infrastructure
  • Implement a job queue (e.g., Bull, Agenda, or database-backed queue)
  • Create a separate worker process to handle report generation jobs
  • Store job state in a database for persistence
2. Modified Submit Flow
// Instead of blocking, return immediately with job ID
async function submit(formData?: FormData, skip?: boolean) {
  const jobId = nanoid()
  
  // Enqueue the job for background processing
  await queue.add('report-generation', {
    jobId,
    formData,
    skip
  })
  
  // Return immediately with job ID
  return {
    jobId,
    status: 'processing'
  }
}
3. Status Checking Mechanism
  • Create a new server action to check job status
  • Implement polling or websocket updates on the client
  • Stream partial results as they become available from the worker
4. Worker Process
  • Move the current processEvents() and processResolutionSearch() logic to a worker
  • Update AIState progressively as results are generated
  • Store intermediate results in the database

Notes

This is a significant architectural change that requires implementing a job queue system, worker processes, and status tracking infrastructure. The current streaming approach in app/actions.tsx provides progressive UI updates but still blocks the server action. True asynchronous processing would require background job processing with a queue system like Bull or a database-backed solution. The existing optimizations in OPTIMIZATION_SUMMARY.md focus on reducing re-renders and caching, not on making the actual generation process non-blocking.

Wiki pages you might want to explore:

Citations

File: app/actions.tsx (L36-42)

async function submit(formData?: FormData, skip?: boolean) {
  'use server'

  const aiState = getMutableAIState<typeof AI>()
  const uiStream = createStreamableUI()
  const isGenerating = createStreamableValue(true)
  const isCollapsed = createStreamableValue(false)

File: app/actions.tsx (L223-223)

    processResolutionSearch();

File: app/actions.tsx (L516-550)

    while (
      useSpecificAPI
        ? answer.length === 0
        : answer.length === 0 && !errorOccurred
    ) {
      const { fullResponse, hasError, toolResponses } = await researcher(
        currentSystemPrompt,
        uiStream,
        streamText,
        messages,
        mapProvider,
        useSpecificAPI,
        drawnFeatures
      )
      answer = fullResponse
      toolOutputs = toolResponses
      errorOccurred = hasError

      if (toolOutputs.length > 0) {
        toolOutputs.map(output => {
          aiState.update({
            ...aiState.get(),
            messages: [
              ...aiState.get().messages,
              {
                id: groupeId,
                role: 'tool',
                content: JSON.stringify(output.result),
                name: output.toolName,
                type: 'tool'
              }
            ]
          })
        })
      }

File: app/actions.tsx (L619-624)

  return {
    id: nanoid(),
    isGenerating: isGenerating.value,
    component: uiStream.value,
    isCollapsed: isCollapsed.value
  }

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading the submit server action in app/actions.tsx, including processResolutionSearch, processEvents, and the researcher loop. Compare the current streaming behavior with OPTIMIZATION_SUMMARY.md and the linked orchestration wiki pages before choosing a queue and persistence approach. Done means report generation returns a job ID promptly, background work tracks status and intermediate results, and clients receive progress updates.

Written by the indexing model from the issue text.

Assessment

Tech stack
nextjs, typescript
Domain
backend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.