Skip to content

Commit 455bdf0

Browse files
authored
Fix demo slowness (#133)
* chore: add static and runtime configurations, implement skeleton loading, and update auth handling - Set dynamic to 'force-static' for specific pages to optimize static rendering - Set runtime to 'edge' for sign-in and sign-up pages for edge functions - Introduce SkeletonTable and Skeleton components for improved loading states - Update header-auth and website-analyzer-form to manage user state with useEffect - Enhance example links component to fetch login status asynchronously - Minor UI adjustments for sign-in, sign-up, and homepage components to handle loading and auth states * refactor: move data loading logic outside useEffect to prevent race conditions - Extracted the data fetching and initialization code from the initial useEffect - Ensured data is loaded after subscription setup to avoid race conditions - Maintained existing state updates and loading state management - Improved code clarity and separation of concerns in the component * chore: update environment variables and configure GitHub OAuth provider - Added GITHUB_OAUTH_CLIENT_ID and GITHUB_OAUTH_CLIENT_SECRET to environment example - Enabled GitHub external auth in the configuration with environment variable references - Updated redirect URI for OAuth callback to localhost - Minor formatting adjustments in environment and config files * chore: add scripts for managing local Supabase instance in playground package - Introduced start-supabase, stop-supabase, and restart-supabase scripts for easier local development - Updated package.json with commands to start, stop, and restart Supabase - Included a script to serve functions and generate TypeScript types for database schema * chore: update script references and commands in package.json and add a new helper script Refactored package.json to replace npx commands with local script invocations for better consistency and control. Added a new executable script for managing Supabase environment variables and commands, improving developer experience and script maintainability. * feat: enhance auth pages with loading states, improve user feedback, and add logging - Added isLoading state to sign-in and sign-up forms for better UX during async actions - Disabled inputs and buttons during loading to prevent duplicate submissions - Updated GithubButton to support external loading state and show spinner - Implemented useEffect in sign-up page to process searchParams and display messages - Added console logs in auth callback route for debugging code exchange process - Enhanced header-auth component with auth state change logging for better monitoring - Updated supabase config with explicit redirect URL and additional redirect URLs for OAuth - Refactored submit-button to show spinner during pending state - Overall improvements for user feedback, debugging, and code consistency * fix: prevent default form submission and handle loading state in auth components - Added e.preventDefault() to form onSubmit handler in sign-in page - Updated GithubButton to reset loading state on error handling - Ensures consistent loading state management across authentication UI components * style: improve layout and UI consistency across components - Add relative positioning to main container for layout stability - Extend footer to be fixed at bottom with background and backdrop blur - Adjust sidebar styling with consistent border and opacity states - Enhance border and overflow styles in flow run details component - Update analysis UI container with background and margin for better spacing * chore: update pgflow to 0.2.4
1 parent edc7d15 commit 455bdf0

File tree

6 files changed

+146
-16
lines changed

6 files changed

+146
-16
lines changed

examples/playground/components/example-links.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,23 @@
11
'use client';
22

33
import { useStartAnalysis } from '@/lib/hooks/use-start-analysis';
4+
import { useEffect, useState } from 'react';
5+
import { createClient } from '@/utils/supabase/client';
46
import { exampleLinks } from '@/lib/example-links';
57
import { useLoadingState } from './loading-state-provider';
68

79
export default function ExampleLinks() {
810
const { start, isPending, error: startError } = useStartAnalysis();
11+
const [isLoggedIn, setIsLoggedIn] = useState<boolean | null>(null);
12+
const supabase = createClient();
913
const { setLoading } = useLoadingState();
1014

15+
useEffect(() => {
16+
supabase.auth.getUser().then(({ data }) => {
17+
setIsLoggedIn(!!data.user);
18+
});
19+
}, []);
20+
1121
// Function to handle example link clicks
1222
const handleExampleClick = (e: React.MouseEvent<HTMLAnchorElement>, url: string) => {
1323
e.preventDefault();

examples/playground/components/flow-run-provider.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ export function FlowRunProvider({ runId, children }: FlowRunProviderProps) {
112112

113113

114114

115+
115116
useEffect(() => {
116117
if (!runId) return;
117118

examples/playground/components/website-analyzer-form.tsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
'use client';
22

33
import { useStartAnalysis } from '@/lib/hooks/use-start-analysis';
4+
import { useEffect, useState } from 'react';
5+
import { createClient } from '@/utils/supabase/client';
46
import { Label } from '@/components/ui/label';
57
import { Input } from '@/components/ui/input';
68
import { FormMessage } from '@/components/form-message';
@@ -9,8 +11,16 @@ import { useLoadingState } from './loading-state-provider';
911

1012
export default function WebsiteAnalyzerForm() {
1113
const { start: startAnalysis, isPending, error: formError } = useStartAnalysis();
14+
const [isLoggedIn, setIsLoggedIn] = useState<boolean | null>(null);
15+
const supabase = createClient();
1216
const { setLoading } = useLoadingState();
1317

18+
useEffect(() => {
19+
supabase.auth.getUser().then(({ data }) => {
20+
setIsLoggedIn(!!data.user);
21+
});
22+
}, []);
23+
1424
async function handleAnalyzeWebsite(formData: FormData) {
1525
const url = formData.get('url') as string;
1626

@@ -49,6 +59,14 @@ export default function WebsiteAnalyzerForm() {
4959
</SubmitButton>
5060
{formError && <FormMessage message={{ error: formError }} />}
5161
</form>
62+
{isLoggedIn === false && (
63+
<div className="mt-4 p-4 bg-yellow-50 border border-yellow-200 rounded-md">
64+
<p className="text-yellow-800">
65+
You'll need to sign in to analyze websites. When you click the
66+
button, you'll be redirected to the sign-in page.
67+
</p>
68+
</div>
69+
)}
5270
</div>
5371
);
5472
}

examples/playground/supabase/functions/deno.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"imports": {
3-
"@pgflow/dsl": "npm:@pgflow/dsl@0.1.22",
4-
"@pgflow/edge-worker": "jsr:@pgflow/edge-worker@0.1.22",
3+
"@pgflow/dsl": "npm:@pgflow/dsl@0.2.4",
4+
"@pgflow/edge-worker": "jsr:@pgflow/edge-worker@0.2.4",
55
"@supabase/supabase-js": "jsr:@supabase/supabase-js@^2.49.4",
66
"groq-sdk": "npm:groq-sdk@^0.20.1",
77
"sanitize-html": "npm:sanitize-html@^2.16.0",

examples/playground/supabase/functions/deno.lock

Lines changed: 14 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
-- Modify "poll_for_tasks" function
2+
CREATE OR REPLACE FUNCTION "pgflow"."poll_for_tasks" ("queue_name" text, "vt" integer, "qty" integer, "max_poll_seconds" integer DEFAULT 5, "poll_interval_ms" integer DEFAULT 100) RETURNS SETOF "pgflow"."step_task_record" LANGUAGE plpgsql SET "search_path" = '' AS $$
3+
declare
4+
msg_ids bigint[];
5+
begin
6+
-- First statement: Read messages and capture their IDs
7+
-- This gets its own snapshot and can see newly committed messages
8+
select array_agg(msg_id)
9+
into msg_ids
10+
from pgflow.read_with_poll(
11+
queue_name,
12+
vt,
13+
qty,
14+
max_poll_seconds,
15+
poll_interval_ms
16+
);
17+
18+
-- If no messages were read, return empty set
19+
if msg_ids is null or array_length(msg_ids, 1) is null then
20+
return;
21+
end if;
22+
23+
-- Second statement: Process tasks with fresh snapshot
24+
-- This can now see step_tasks that were committed during the poll
25+
return query
26+
with tasks as (
27+
select
28+
task.flow_slug,
29+
task.run_id,
30+
task.step_slug,
31+
task.task_index,
32+
task.message_id
33+
from pgflow.step_tasks as task
34+
where task.message_id = any(msg_ids)
35+
and task.status = 'queued'
36+
),
37+
increment_attempts as (
38+
update pgflow.step_tasks
39+
set attempts_count = attempts_count + 1
40+
from tasks
41+
where step_tasks.message_id = tasks.message_id
42+
and status = 'queued'
43+
),
44+
runs as (
45+
select
46+
r.run_id,
47+
r.input
48+
from pgflow.runs r
49+
where r.run_id in (select run_id from tasks)
50+
),
51+
deps as (
52+
select
53+
st.run_id,
54+
st.step_slug,
55+
dep.dep_slug,
56+
dep_task.output as dep_output
57+
from tasks st
58+
join pgflow.deps dep on dep.flow_slug = st.flow_slug and dep.step_slug = st.step_slug
59+
join pgflow.step_tasks dep_task on
60+
dep_task.run_id = st.run_id and
61+
dep_task.step_slug = dep.dep_slug and
62+
dep_task.status = 'completed'
63+
),
64+
deps_outputs as (
65+
select
66+
d.run_id,
67+
d.step_slug,
68+
jsonb_object_agg(d.dep_slug, d.dep_output) as deps_output
69+
from deps d
70+
group by d.run_id, d.step_slug
71+
),
72+
timeouts as (
73+
select
74+
task.message_id,
75+
coalesce(step.opt_timeout, flow.opt_timeout) + 2 as vt_delay
76+
from tasks task
77+
join pgflow.flows flow on flow.flow_slug = task.flow_slug
78+
join pgflow.steps step on step.flow_slug = task.flow_slug and step.step_slug = task.step_slug
79+
)
80+
select
81+
st.flow_slug,
82+
st.run_id,
83+
st.step_slug,
84+
jsonb_build_object('run', r.input) ||
85+
coalesce(dep_out.deps_output, '{}'::jsonb) as input,
86+
st.message_id as msg_id
87+
from tasks st
88+
join runs r on st.run_id = r.run_id
89+
left join deps_outputs dep_out on
90+
dep_out.run_id = st.run_id and
91+
dep_out.step_slug = st.step_slug
92+
cross join lateral (
93+
-- TODO: this is slow because it calls set_vt for each row, and set_vt
94+
-- builds dynamic query from string every time it is called
95+
-- implement set_vt_batch(msgs_ids bigint[], vt_delays int[])
96+
select pgmq.set_vt(queue_name, st.message_id,
97+
(select t.vt_delay from timeouts t where t.message_id = st.message_id)
98+
)
99+
) set_vt;
100+
end;
101+
$$;

0 commit comments

Comments
 (0)