/v1/announcements/changes El punto final es el punto de emergencia de la encuesta sin servidor cuando no está disponible una conexión SSE persistente.
Supabase es un hogar natural para un producto fintech que necesita autenticación, Postgres, seguridad a nivel de fila y funciones ligeras del lado del servidor. Flujos de la EES para los oyentes siempre en.
La elección importante del diseño es donde cada trabajo se ejecuta. Funciones de borde de supabase Los procesadores HTTP basados en Deno son los más adecuados para receptores webhook, proxies REST autenticados y trabajos de votación programados. No son el lugar adecuado para mantener abierto un flujo indefinido. Si su producto necesita un escuchador SSE, ejecute ese escuchado en un trabajador siempre activo y escriba los eventos resultantes en Supabase.
Utilice FXMacroData webhooks para actualizar Supabase sólo cuando se procesa una versión de macro correspondiente.
Programe una función de borde que haga encuestas /v1/announcements/changes con un cursor.
Ejecute SSE en Railway, Fly.io, un VPS u otro trabajador siempre activo, luego escriba eventos en Supabase.
1. Elige el modelo de entrega correcto
No haga que cada usuario, página o encuesta de trabajo cron sea cada punto final de FXMacroData. Ponga una integración del lado del servidor detrás de su producto, persista en el estado de liberación que necesita y deje que su aplicación lea desde Supabase.
| El patrón | Usarlo para | Aplicación de base |
|---|---|---|
| REST más reciente | Estado inicial de la aplicación, reparación de la caché y arranque diario. | Es bueno para un trabajo corto de Edge Function. |
| Las webhooks | Actualizaciones basadas en versiones con devoluciones de llamadas HTTPS firmadas. | Mejor para las funciones de Edge. |
| Cambios en el punto final | Encuestas basadas en el cursor cuando los webhooks entrantes no son adecuados. | Es bueno para el Cron de la base de datos más una función de borde. |
| Flujo de la EES | Escuchas en vivo que pueden volver a conectarse y mantenerse calientes. | Corra fuera de Edge Functions, luego escriba a Supabase. |
2. Crear las tablas de supabase
Comience con una tabla de eventos duradera y una pequeña tabla del estado para el cursor de cambios.
create table public.fxmd_macro_events (
event_id text primary key,
source text not null,
currency text not null,
indicator text not null,
announcement_at timestamptz,
payload jsonb not null,
received_at timestamptz not null default now()
);
create table public.fxmd_integration_state (
name text primary key,
cursor text,
updated_at timestamptz not null default now()
);
Si los clientes pueden ver la salida con FXMacroData dentro de su producto, revise el Redistribución comercial La arquitectura de la aplicación todavía puede usar Supabase, pero el derecho comercial es diferente cuando los datos macro son visibles fuera de su propio equipo.
3. Guarde los secretos en un lugar seguro
¿ Cómo ? Secreto de la función de supabase Edge No exponga su clave de la API de FXMacroData en el código del navegador, clientes móviles o filas de base de datos accesibles por el cliente.
supabase secrets set FXMD_API_KEY=YOUR_API_KEY
supabase secrets set FXMD_WEBHOOK_SECRET=whsec_YOUR_SIGNING_SECRET
supabase secrets set SUPABASE_SERVICE_ROLE_KEY=YOUR_SERVICE_ROLE_KEY
Dentro de una función de borde, leer secretos con Deno.env.get("FXMD_API_KEY")Supabase documenta esto como la forma estándar de acceder a los secretos de Deno.
4. Bootstrap Estado de la macro actual
¿ Cómo ? /v1/announcements/{currency}/latest Esto es un trabajo de arranque y reparación, no algo que cada sesión de cliente debe ejecutar de forma independiente.
import { createClient } from "https://esm.sh/@supabase/supabase-js@2";
Deno.serve(async () => {
const db = createClient(Deno.env.get("SUPABASE_URL")!,
Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!);
const apiKey = Deno.env.get("FXMD_API_KEY")!;
const currencies = ["usd", "eur", "gbp", "jpy", "aud", "cad", "chf", "nzd"];
for (const currency of currencies) {
const url = `https://api.fxmacrodata.com/v1/announcements/${currency}/latest?api_key=${apiKey}`;
const latest = await (await fetch(url)).json();
await db.from("fxmd_macro_events").upsert({
event_id: `${currency}_latest_bootstrap`,
source: "latest",
currency,
indicator: "latest",
payload: latest
});
}
return Response.json({ ok: true, currencies: currencies.length });
});
Para los gráficos históricos, busque solo los indicadores que realmente muestra y almacenar en caché el resultado.
5. Recibir las webhooks de FXMacroData
Las webhooks son la integración de la función de borde de Supabase más limpia. FXMacroData llama a su función HTTPS pública cuando se procesa un anuncio de coincidencia. Su función verifica la firma, almacena el evento y regresa rápidamente.
Crear una suscripción con un destino como https://PROJECT_REF.functions.supabase.co/fxmd-webhookSe trata de:
curl -X POST "https://api.fxmacrodata.com/v1/webhooks/subscriptions?api_key=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://PROJECT_REF.functions.supabase.co/fxmd-webhook",
"events": ["announcement"],
"currencies": ["usd", "eur"],
"indicators": ["inflation", "policy_rate"],
"description": "Supabase macro release receiver"
}'
Usa el devuelto . signing_secret ¿ Cómo ? FXMD_WEBHOOK_SECRET. El asistente a continuación reconstruye la entrada de firma FXMacroData desde la marca de tiempo, ID de evento y el cuerpo de la solicitud en bruto.
async function hmacHex(secret: string, message: string) {
const enc = new TextEncoder();
const key = await crypto.subtle.importKey(
"raw", enc.encode(secret), { name: "HMAC", hash: "SHA-256" },
false, ["sign"]
);
const digest = await crypto.subtle.sign("HMAC", key, enc.encode(message));
return [...new Uint8Array(digest)]
.map((b) => b.toString(16).padStart(2, "0"))
.join("");
}
function safeEqual(a: string, b: string) {
const aa = new TextEncoder().encode(a);
const bb = new TextEncoder().encode(b);
let diff = aa.length ^ bb.length;
for (let i = 0; i < Math.max(aa.length, bb.length); i++) {
diff |= (aa[i] ?? 0) ^ (bb[i] ?? 0);
}
return diff === 0;
}
async function verifyFxmd(req: Request, body: string) {
const ts = req.headers.get("x-fxmd-timestamp") ?? "";
const eventId = req.headers.get("x-fxmd-event-id") ?? "";
const supplied = (req.headers.get("x-fxmd-signature") ?? "").replace(/^v1=/, "");
const secret = Deno.env.get("FXMD_WEBHOOK_SECRET")!;
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
const expected = await hmacHex(secret, `${ts}.${eventId}.${body}`);
return safeEqual(expected, supplied);
}
El receptor de la función Edge debe almacenar el ID de evento antes de realizar cualquier trabajo más pesado. Eso evita que los intentos de reinicio de webhook creen alertas duplicadas o actualizaciones repetidas del panel de control.
import { createClient } from "https://esm.sh/@supabase/supabase-js@2";
Deno.serve(async (req) => {
const body = await req.text();
if (!(await verifyFxmd(req, body))) return new Response("invalid", { status: 401 });
const payload = JSON.parse(body);
const event = payload.data ?? {};
const db = createClient(Deno.env.get("SUPABASE_URL")!,
Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!);
const { error } = await db.from("fxmd_macro_events").upsert({
event_id: event.event_id,
source: "webhook",
currency: event.currency,
indicator: event.indicator,
announcement_at: event.latest_announcement?.announcement_datetime,
payload
}, { onConflict: "event_id", ignoreDuplicates: true });
return new Response(error ? "store failed" : null, { status: error ? 500 : 204 });
});
La configuración completa del webhook, el comportamiento de los intentos de reinicio, los registros de entrega y los encabezados de firma están cubiertos en el Documentación de las webhooks de FXMacroData y el artículo de anuncio de webhooks- ¿ Qué ?
6. Encuesta de cambios recientes de las funciones de borde
Si no es posible utilizar webhooks entrantes, utilice el punto final de cambios en lugar de cada moneda e indicador. El punto final devuelve eventos de liberación recientes desde el mismo fanout en vivo utilizado por SSE. next_cursor y lo devuelvo como since en la próxima encuesta.
curl "https://api.fxmacrodata.com/v1/announcements/changes?currencies=g10&payload=full&limit=100&api_key=YOUR_API_KEY"
import { createClient } from "https://esm.sh/@supabase/supabase-js@2";
Deno.serve(async () => {
const db = createClient(Deno.env.get("SUPABASE_URL")!,
Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!);
const apiKey = Deno.env.get("FXMD_API_KEY")!;
const { data: state } = await db.from("fxmd_integration_state")
.select("cursor").eq("name", "g10_changes").maybeSingle();
const url = new URL("https://api.fxmacrodata.com/v1/announcements/changes");
for (const [key, value] of [["currencies", "g10"], ["payload", "full"],
["limit", "100"], ["api_key", apiKey]]) url.searchParams.set(key, value);
if (state?.cursor) url.searchParams.set("since", state.cursor);
const json = await (await fetch(url)).json();
for (const event of json.data ?? []) {
await db.from("fxmd_macro_events").upsert({
event_id: event.event_id, source: "changes",
currency: event.currency, indicator: event.indicator, payload: event
}, { onConflict: "event_id", ignoreDuplicates: true });
}
await db.from("fxmd_integration_state")
.upsert({ name: "g10_changes", cursor: json.next_cursor });
return Response.json({ count: json.count, has_more: json.has_more });
});
Ponga el encuestador con Funciones programadas de supabaseDurante las horas de silencio, la respuesta normalmente estará vacía pero es barata de procesar.
select cron.schedule(
'fxmd-g10-changes',
'*/5 * * * *',
$$
select net.http_post(
url := 'https://PROJECT_REF.functions.supabase.co/fxmd-changes-poller',
headers := '{"Authorization":"Bearer YOUR_SUPABASE_FUNCTION_SECRET"}'::jsonb
);
$$
);
Si el cursor es más antiguo que la ventana de retención de punto final, ejecute la función de arranque de nuevo y continúe con la más reciente next_cursorEsto es más sencillo y seguro que tratar de recuperar las emisiones perdidas mediante la ampliación de las encuestas por indicador.
7. Utilice el SSE de un trabajador siempre activo
Las corrientes FXMacroData SSE son útiles cuando un proceso puede mantener una conexión abierta y volver a conectarse con Last-Event-ID. Las funciones de borde de Supabase son manipuladores de solicitudes, y Supa base documenta límites separados para la duración, el tiempo de inactividad, la memoria y la CPU. Por esa razón, no construya el cliente SSE dentro de una función de borde.
En su lugar, ejecute el escuchador de transmisión en un proceso siempre encendido:
curl -N "https://api.fxmacrodata.com/v1/stream/events?currencies=g10&payload=full&api_key=YOUR_API_KEY"
El trabajador puede ser pequeño: conectar con https://api.fxmacrodata.com/v1/stream/events- ¿ Qué ? announcement Los eventos, escribe cada uno event_id En el fxmd_macro_events, y volver a conectar utilizando el ID de evento recibida última. Documentación de los flujos de la EES cuando necesites este camino.
8. Lista de verificación de la producción
Solo las funciones de borde o los trabajadores siempre activados deben llamar a FXMacroData con su clave de API.
¿ Cómo ? event_id como la clave primaria para que los webhooks, las reintentas, las reconexiones SSE y las encuestas se superpongan de forma segura.
Utilice webhooks o encuestas de cambios en lugar de llamar /calendar/ ¿ Qué ? /announcements/ por cada bala cada minuto.
Deja que tu aplicación lea filas listas para la visualización desde Supabase en lugar de llamar a FXMacroData desde cada vista de página.
Preguntas frecuentes
¿Debería usar webhooks o los cambios de punto final con Supabase?
Utilice webhooks cuando su función de borde de Supabase pueda recibir llamadas públicas de retorno HTTPS. /v1/announcements/changes cuando necesitas una encuesta sin servidor programada.
¿Puedo ejecutar el flujo FXMacroData SSE dentro de una función de borde de Supabase?
Utilice un trabajador siempre activo para SSE. Las funciones de borde son más adecuadas para receptores webhook, proxies REST y trabajos programados que terminan rápidamente.
¿Necesito cargar datos históricos todas las noches?
Normalmente no. arranque el estado actual con /latest, almacenar los eventos de lanzamiento a medida que llegan, y recuperar series históricas sólo para los indicadores que su producto realmente muestra o analiza.
¿Qué punto final FXMacroData debe una encuesta de trabajo cron Supabase?
Me gusta . https://api.fxmacrodata.com/v1/announcements/changes Está diseñado para clientes sin servidor que no pueden mantener una conexión SSE abierta.
Empieza
Comience con la ruta de webhook si su proyecto de Supabase puede exponer una función de borde pública. Añadir el cuestionador de cambios como una alternativa para las devoluciones de llamadas perdidas o entornos que no pueden recibir webhooks entrantes. Use REST /latest La información que se proporciona a los trabajadores de la empresa es de gran utilidad para la puesta en marcha y recuperación, y para mantener el SSE en un pequeño equipo siempre activo cuando se necesite un flujo continuo.
Páginas de referencia: Las redes web de FXMacroData¿ Qué ? Flujos de FXMacroData SSE¿ Qué ? puntos finales de anuncio, y Funciones de borde de supabase- ¿ Qué ?