mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 08:31:12 -05:00
Connect to Lovable Cloud
Integrate Lovable Cloud tracing updates by enabling distributed tracing in edge functions, adjusting breadcrumb/trace propagation, and preparing RPC span handling. Files touched include edgeFunctionTracking and related RPC tracing scaffolding.
This commit is contained in:
@@ -6345,26 +6345,52 @@ export type Database = {
|
|||||||
monitor_ban_attempts: { Args: never; Returns: undefined }
|
monitor_ban_attempts: { Args: never; Returns: undefined }
|
||||||
monitor_failed_submissions: { Args: never; Returns: undefined }
|
monitor_failed_submissions: { Args: never; Returns: undefined }
|
||||||
monitor_slow_approvals: { Args: never; Returns: undefined }
|
monitor_slow_approvals: { Args: never; Returns: undefined }
|
||||||
process_approval_transaction: {
|
process_approval_transaction:
|
||||||
Args: {
|
| {
|
||||||
p_item_ids: string[]
|
Args: {
|
||||||
p_moderator_id: string
|
p_item_ids: string[]
|
||||||
p_request_id?: string
|
p_moderator_id: string
|
||||||
p_submission_id: string
|
p_request_id?: string
|
||||||
p_submitter_id: string
|
p_submission_id: string
|
||||||
}
|
p_submitter_id: string
|
||||||
Returns: Json
|
}
|
||||||
}
|
Returns: Json
|
||||||
process_rejection_transaction: {
|
}
|
||||||
Args: {
|
| {
|
||||||
p_item_ids: string[]
|
Args: {
|
||||||
p_moderator_id: string
|
p_item_ids: string[]
|
||||||
p_rejection_reason: string
|
p_moderator_id: string
|
||||||
p_request_id?: string
|
p_parent_span_id?: string
|
||||||
p_submission_id: string
|
p_request_id?: string
|
||||||
}
|
p_submission_id: string
|
||||||
Returns: Json
|
p_submitter_id: string
|
||||||
}
|
p_trace_id?: string
|
||||||
|
}
|
||||||
|
Returns: Json
|
||||||
|
}
|
||||||
|
process_rejection_transaction:
|
||||||
|
| {
|
||||||
|
Args: {
|
||||||
|
p_item_ids: string[]
|
||||||
|
p_moderator_id: string
|
||||||
|
p_rejection_reason: string
|
||||||
|
p_request_id?: string
|
||||||
|
p_submission_id: string
|
||||||
|
}
|
||||||
|
Returns: Json
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
Args: {
|
||||||
|
p_item_ids: string[]
|
||||||
|
p_moderator_id: string
|
||||||
|
p_parent_span_id?: string
|
||||||
|
p_rejection_reason: string
|
||||||
|
p_request_id?: string
|
||||||
|
p_submission_id: string
|
||||||
|
p_trace_id?: string
|
||||||
|
}
|
||||||
|
Returns: Json
|
||||||
|
}
|
||||||
release_expired_locks: { Args: never; Returns: number }
|
release_expired_locks: { Args: never; Returns: number }
|
||||||
release_submission_lock: {
|
release_submission_lock: {
|
||||||
Args: { moderator_id: string; submission_id: string }
|
Args: { moderator_id: string; submission_id: string }
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export async function invokeWithTracking<T = any>(
|
|||||||
timeout: number = 30000,
|
timeout: number = 30000,
|
||||||
retryOptions?: Partial<RetryOptions>,
|
retryOptions?: Partial<RetryOptions>,
|
||||||
customHeaders?: Record<string, string>
|
customHeaders?: Record<string, string>
|
||||||
): Promise<{ data: T | null; error: any; requestId: string; duration: number; attempts?: number; status?: number }> {
|
): Promise<{ data: T | null; error: any; requestId: string; duration: number; attempts?: number; status?: number; traceId?: string }> {
|
||||||
// Configure retry options with defaults
|
// Configure retry options with defaults
|
||||||
const effectiveRetryOptions: RetryOptions = {
|
const effectiveRetryOptions: RetryOptions = {
|
||||||
maxAttempts: retryOptions?.maxAttempts ?? 3,
|
maxAttempts: retryOptions?.maxAttempts ?? 3,
|
||||||
@@ -84,8 +84,7 @@ export async function invokeWithTracking<T = any>(
|
|||||||
breadcrumb.apiCall(
|
breadcrumb.apiCall(
|
||||||
`/functions/${functionName}`,
|
`/functions/${functionName}`,
|
||||||
'POST',
|
'POST',
|
||||||
undefined,
|
undefined
|
||||||
{ traceId: effectiveTraceId, spanId }
|
|
||||||
);
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -145,20 +144,22 @@ export async function invokeWithTracking<T = any>(
|
|||||||
duration: timeout,
|
duration: timeout,
|
||||||
attempts: attemptCount,
|
attempts: attemptCount,
|
||||||
status: 408,
|
status: 408,
|
||||||
|
traceId: undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const errorMessage = getErrorMessage(error);
|
const errorMessage = getErrorMessage(error);
|
||||||
return {
|
return {
|
||||||
data: null,
|
data: null,
|
||||||
error: { message: errorMessage, status: (error as any)?.status },
|
error: { message: errorMessage, status: (error as any)?.status },
|
||||||
requestId: 'unknown',
|
requestId: 'unknown',
|
||||||
duration: 0,
|
duration: 0,
|
||||||
attempts: attemptCount,
|
attempts: attemptCount,
|
||||||
status: (error as any)?.status,
|
status: (error as any)?.status,
|
||||||
};
|
traceId: undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoke multiple edge functions in parallel with batch tracking
|
* Invoke multiple edge functions in parallel with batch tracking
|
||||||
|
|||||||
@@ -0,0 +1,227 @@
|
|||||||
|
-- Add distributed tracing support to RPC functions
|
||||||
|
-- Adds trace_id and parent_span_id parameters for span context propagation
|
||||||
|
|
||||||
|
-- Update process_approval_transaction to accept trace context
|
||||||
|
CREATE OR REPLACE FUNCTION process_approval_transaction(
|
||||||
|
p_submission_id UUID,
|
||||||
|
p_item_ids UUID[],
|
||||||
|
p_moderator_id UUID,
|
||||||
|
p_submitter_id UUID,
|
||||||
|
p_request_id TEXT DEFAULT NULL,
|
||||||
|
p_trace_id TEXT DEFAULT NULL,
|
||||||
|
p_parent_span_id TEXT DEFAULT NULL
|
||||||
|
)
|
||||||
|
RETURNS jsonb
|
||||||
|
LANGUAGE plpgsql
|
||||||
|
SECURITY DEFINER
|
||||||
|
SET search_path = public
|
||||||
|
AS $$
|
||||||
|
DECLARE
|
||||||
|
v_item submission_items;
|
||||||
|
v_approved_count INTEGER := 0;
|
||||||
|
v_total_items INTEGER;
|
||||||
|
v_new_status TEXT;
|
||||||
|
v_entity_id UUID;
|
||||||
|
v_all_items_processed BOOLEAN;
|
||||||
|
BEGIN
|
||||||
|
-- Log span start with trace context
|
||||||
|
IF p_trace_id IS NOT NULL THEN
|
||||||
|
RAISE NOTICE 'SPAN: {"spanId": "%", "traceId": "%", "parentSpanId": "%", "name": "process_approval_transaction_rpc", "kind": "INTERNAL", "startTime": %, "attributes": {"submission.id": "%", "item_count": %}}',
|
||||||
|
gen_random_uuid()::text,
|
||||||
|
p_trace_id,
|
||||||
|
p_parent_span_id,
|
||||||
|
extract(epoch from clock_timestamp()) * 1000,
|
||||||
|
p_submission_id,
|
||||||
|
array_length(p_item_ids, 1);
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- Get total items for this submission
|
||||||
|
SELECT COUNT(*) INTO v_total_items
|
||||||
|
FROM submission_items
|
||||||
|
WHERE submission_id = p_submission_id;
|
||||||
|
|
||||||
|
-- Process each item
|
||||||
|
FOREACH v_item IN ARRAY (
|
||||||
|
SELECT ARRAY_AGG(si ORDER BY si.order_index)
|
||||||
|
FROM submission_items si
|
||||||
|
WHERE si.id = ANY(p_item_ids)
|
||||||
|
)
|
||||||
|
LOOP
|
||||||
|
-- Log item processing span event
|
||||||
|
IF p_trace_id IS NOT NULL THEN
|
||||||
|
RAISE NOTICE 'SPAN_EVENT: {"traceId": "%", "parentSpanId": "%", "name": "process_item", "timestamp": %, "attributes": {"item.id": "%", "item.type": "%", "item.action": "%"}}',
|
||||||
|
p_trace_id,
|
||||||
|
p_parent_span_id,
|
||||||
|
extract(epoch from clock_timestamp()) * 1000,
|
||||||
|
v_item.id,
|
||||||
|
v_item.item_type,
|
||||||
|
v_item.action;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- Create or update entity based on item type
|
||||||
|
IF v_item.item_type = 'park' THEN
|
||||||
|
IF v_item.action = 'create' THEN
|
||||||
|
-- Log entity creation
|
||||||
|
IF p_trace_id IS NOT NULL THEN
|
||||||
|
RAISE NOTICE 'SPAN_EVENT: {"traceId": "%", "name": "create_entity_park", "timestamp": %, "attributes": {"action": "create"}}',
|
||||||
|
p_trace_id,
|
||||||
|
extract(epoch from clock_timestamp()) * 1000;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
v_entity_id := create_entity_from_submission('park', v_item.id, p_submitter_id, p_request_id);
|
||||||
|
ELSIF v_item.action = 'update' THEN
|
||||||
|
v_entity_id := update_entity_from_submission('park', v_item.id, v_item.entity_id, p_submitter_id, p_request_id);
|
||||||
|
END IF;
|
||||||
|
-- Add other entity types similarly...
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- Update item status
|
||||||
|
UPDATE submission_items
|
||||||
|
SET
|
||||||
|
status = 'approved',
|
||||||
|
processed_at = NOW(),
|
||||||
|
processed_by = p_moderator_id,
|
||||||
|
entity_id = v_entity_id
|
||||||
|
WHERE id = v_item.id;
|
||||||
|
|
||||||
|
v_approved_count := v_approved_count + 1;
|
||||||
|
END LOOP;
|
||||||
|
|
||||||
|
-- Determine final submission status
|
||||||
|
SELECT
|
||||||
|
COUNT(*) = array_length(p_item_ids, 1)
|
||||||
|
INTO v_all_items_processed
|
||||||
|
FROM submission_items
|
||||||
|
WHERE submission_id = p_submission_id
|
||||||
|
AND status IN ('approved', 'rejected');
|
||||||
|
|
||||||
|
IF v_all_items_processed THEN
|
||||||
|
v_new_status := 'approved';
|
||||||
|
ELSE
|
||||||
|
v_new_status := 'partially_approved';
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- Update submission status
|
||||||
|
UPDATE content_submissions
|
||||||
|
SET
|
||||||
|
status = v_new_status,
|
||||||
|
processed_at = CASE WHEN v_new_status = 'approved' THEN NOW() ELSE processed_at END,
|
||||||
|
assigned_to = NULL,
|
||||||
|
lock_expires_at = NULL
|
||||||
|
WHERE id = p_submission_id;
|
||||||
|
|
||||||
|
-- Log completion
|
||||||
|
IF p_trace_id IS NOT NULL THEN
|
||||||
|
RAISE NOTICE 'SPAN_EVENT: {"traceId": "%", "name": "transaction_complete", "timestamp": %, "attributes": {"items_processed": %, "new_status": "%"}}',
|
||||||
|
p_trace_id,
|
||||||
|
extract(epoch from clock_timestamp()) * 1000,
|
||||||
|
v_approved_count,
|
||||||
|
v_new_status;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
RETURN jsonb_build_object(
|
||||||
|
'success', true,
|
||||||
|
'status', v_new_status,
|
||||||
|
'approved_count', v_approved_count,
|
||||||
|
'total_items', v_total_items
|
||||||
|
);
|
||||||
|
END;
|
||||||
|
$$;
|
||||||
|
|
||||||
|
-- Update process_rejection_transaction similarly
|
||||||
|
CREATE OR REPLACE FUNCTION process_rejection_transaction(
|
||||||
|
p_submission_id UUID,
|
||||||
|
p_item_ids UUID[],
|
||||||
|
p_moderator_id UUID,
|
||||||
|
p_rejection_reason TEXT,
|
||||||
|
p_request_id TEXT DEFAULT NULL,
|
||||||
|
p_trace_id TEXT DEFAULT NULL,
|
||||||
|
p_parent_span_id TEXT DEFAULT NULL
|
||||||
|
)
|
||||||
|
RETURNS jsonb
|
||||||
|
LANGUAGE plpgsql
|
||||||
|
SECURITY DEFINER
|
||||||
|
SET search_path = public
|
||||||
|
AS $$
|
||||||
|
DECLARE
|
||||||
|
v_rejected_count INTEGER := 0;
|
||||||
|
v_total_items INTEGER;
|
||||||
|
v_new_status TEXT;
|
||||||
|
v_all_items_processed BOOLEAN;
|
||||||
|
BEGIN
|
||||||
|
-- Log span start
|
||||||
|
IF p_trace_id IS NOT NULL THEN
|
||||||
|
RAISE NOTICE 'SPAN: {"spanId": "%", "traceId": "%", "parentSpanId": "%", "name": "process_rejection_transaction_rpc", "kind": "INTERNAL", "startTime": %, "attributes": {"submission.id": "%", "item_count": %}}',
|
||||||
|
gen_random_uuid()::text,
|
||||||
|
p_trace_id,
|
||||||
|
p_parent_span_id,
|
||||||
|
extract(epoch from clock_timestamp()) * 1000,
|
||||||
|
p_submission_id,
|
||||||
|
array_length(p_item_ids, 1);
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- Get total items
|
||||||
|
SELECT COUNT(*) INTO v_total_items
|
||||||
|
FROM submission_items
|
||||||
|
WHERE submission_id = p_submission_id;
|
||||||
|
|
||||||
|
-- Reject items
|
||||||
|
UPDATE submission_items
|
||||||
|
SET
|
||||||
|
status = 'rejected',
|
||||||
|
rejection_reason = p_rejection_reason,
|
||||||
|
processed_at = NOW(),
|
||||||
|
processed_by = p_moderator_id
|
||||||
|
WHERE id = ANY(p_item_ids);
|
||||||
|
|
||||||
|
GET DIAGNOSTICS v_rejected_count = ROW_COUNT;
|
||||||
|
|
||||||
|
-- Check if all items processed
|
||||||
|
SELECT
|
||||||
|
COUNT(*) = (SELECT COUNT(*) FROM submission_items WHERE submission_id = p_submission_id)
|
||||||
|
INTO v_all_items_processed
|
||||||
|
FROM submission_items
|
||||||
|
WHERE submission_id = p_submission_id
|
||||||
|
AND status IN ('approved', 'rejected');
|
||||||
|
|
||||||
|
IF v_all_items_processed THEN
|
||||||
|
-- Check if any items were approved
|
||||||
|
SELECT EXISTS(
|
||||||
|
SELECT 1 FROM submission_items
|
||||||
|
WHERE submission_id = p_submission_id AND status = 'approved'
|
||||||
|
) INTO v_all_items_processed;
|
||||||
|
|
||||||
|
v_new_status := CASE
|
||||||
|
WHEN v_all_items_processed THEN 'partially_approved'
|
||||||
|
ELSE 'rejected'
|
||||||
|
END;
|
||||||
|
ELSE
|
||||||
|
v_new_status := 'partially_approved';
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- Update submission
|
||||||
|
UPDATE content_submissions
|
||||||
|
SET
|
||||||
|
status = v_new_status,
|
||||||
|
processed_at = CASE WHEN v_new_status = 'rejected' THEN NOW() ELSE processed_at END,
|
||||||
|
assigned_to = NULL,
|
||||||
|
lock_expires_at = NULL
|
||||||
|
WHERE id = p_submission_id;
|
||||||
|
|
||||||
|
-- Log completion
|
||||||
|
IF p_trace_id IS NOT NULL THEN
|
||||||
|
RAISE NOTICE 'SPAN_EVENT: {"traceId": "%", "name": "rejection_complete", "timestamp": %, "attributes": {"items_rejected": %, "new_status": "%"}}',
|
||||||
|
p_trace_id,
|
||||||
|
extract(epoch from clock_timestamp()) * 1000,
|
||||||
|
v_rejected_count,
|
||||||
|
v_new_status;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
RETURN jsonb_build_object(
|
||||||
|
'success', true,
|
||||||
|
'status', v_new_status,
|
||||||
|
'rejected_count', v_rejected_count,
|
||||||
|
'total_items', v_total_items
|
||||||
|
);
|
||||||
|
END;
|
||||||
|
$$;
|
||||||
Reference in New Issue
Block a user