diff --git a/src/client.ts b/src/client.ts index 032e8d6..61ad02e 100644 --- a/src/client.ts +++ b/src/client.ts @@ -17,11 +17,11 @@ client.use(express.json({ client.use(express.urlencoded({ extended: true })); // Webhook reception -client.post('/order/create', verifyWebhookSignature, handleWebhook); +client.post('/order/create', handleWebhook); // Health check client.get('/health', (req, res) => { - res.status(200).send({ resp: 'OK' }); + res.status(200).send({ resp: 'OK - Client' }); }); export default client; diff --git a/src/config/initial_hosts.ts b/src/config/initial_hosts.ts index aa9fe75..b558ed3 100644 --- a/src/config/initial_hosts.ts +++ b/src/config/initial_hosts.ts @@ -2,7 +2,7 @@ * Configuracion de los host iniciales y a que topics escuchan */ -import { SetupSubscription, SubscriptionData } from "#controllers/subscriptions.types.js" +import { ScheduledEvent, SetupSubscription, SubscriptionData } from "#controllers/subscriptions.types.js" import { webhooksConfig } from "." @@ -22,12 +22,19 @@ export function generateSubscriptions(initialHosts?: SetupSubscription[]) { ...setup }) } - return topicSubscriberMap } +type InitialHost = { + topic: string, + host: string, + port: string, + endpoint: string, + method: "POST" | "PUT" | "DELETE", + secretkey: string, +} -export const INITIAL_HOSTS: SetupSubscription[] = [ +export const INITIAL_HOSTS: InitialHost[] = [ { topic: "order/create", host: "localhost", @@ -35,11 +42,13 @@ export const INITIAL_HOSTS: SetupSubscription[] = [ endpoint: "/order/create", method: "POST", secretkey: webhooksConfig.apiSecret || "1234", - open: new Date, - options: { - period: 1000 - } } ] - +export const INITIAL_EVENTS: ScheduledEvent[] = [ + { + topic: "order/create", + numberOfMessages: 5, + periodMs: 1000 + } +] diff --git a/src/controllers/subscription_manager.ts b/src/controllers/subscription_manager.ts index b626f25..ad37fff 100644 --- a/src/controllers/subscription_manager.ts +++ b/src/controllers/subscription_manager.ts @@ -1,17 +1,22 @@ import { generateHMACSignature } from "#middleware/hmac.js"; import { requestBuilder, shopifyHeaderBuilder } from "#shared/requests.js"; -import { ShopifyEvent, SubscriptionData, SubscriptorData, Topic } from "./subscriptions.types"; +import { ScheduledEvent, ShopifyEvent, SubscriptionData, SubscriptorData, Topic } from "./subscriptions.types"; /** * De scheduler tiene poco + * TODO: + * - No se pueden crear eventos nuevos */ export class EventScheduler { - public eventList: SubscriptorData[] = [] + public eventList: ScheduledEvent[] = [] public activeIntervals: NodeJS.Timeout[] = [] - + public subscriptionManager: SubscriptionManager constructor(args: { - events?: SubscriptorData[], + events?: ScheduledEvent[], + subscriptionManager: SubscriptionManager }) { + this.subscriptionManager = args.subscriptionManager + if (args.events != undefined) { this.eventList = args.events } @@ -20,16 +25,25 @@ export class EventScheduler { private start() { for (const event of this.eventList) { + console.log("Evento", event) let sentMesages = 0 const interval = setInterval(() => { console.log("[Server] Lanzado evento ", event) - if (event.options?.mesages == undefined || event.options?.mesages < 1) + if (event.numberOfMessages == undefined || event.numberOfMessages < 1) { + console.log("xx") return; // Se lannza de continuo + } + + this.subscriptionManager.poll({ + topic: event.topic, + data: { id: 123 } + }) + sentMesages++; - if (sentMesages > event.options.mesages) { + if (sentMesages > event.numberOfMessages) { clearInterval(interval) } - }, event.options?.period ?? 1000) + }, event.periodMs ?? 1000) this.activeIntervals.push(interval) } } @@ -38,13 +52,10 @@ export class EventScheduler { export class SubscriptionManager { private subscriptions: Map = new Map() - public scheduler: EventScheduler constructor( - scheduler: EventScheduler, subs?: typeof this.subscriptions, ) { - this.scheduler = scheduler if (subs != undefined) { this.subscriptions = subs } @@ -64,15 +75,18 @@ export class SubscriptionManager { } public poll(event: ShopifyEvent) { + console.log("!! -- !!") const topic = event.topic if (!this.subscriptions.has(topic)) { - console.error("Topic desconocido: " + topic) + console.error("[Server] Topic desconocido: " + topic) return; } const subscriptors = this.subscriptions.get(topic) + console.log("[Server] Enviando evento a ", subscriptors) + for (const sub of subscriptors!.subscriptors) { const body = { id: 1234 @@ -90,13 +104,14 @@ export class SubscriptionManager { endpoint: sub.endpoint }) request.write(parsedBody) + // Data puede venir en chunks! request.on("data", () => console.log) request.on("end", () => console.log) request.on("error", () => console.error) request.end() - console.debug("Enviado evento a ", sub.host, ":", sub.port, sub.endpoint) + console.log("[Server] Enviado evento a ", sub.host, ":", sub.port, sub.endpoint) } } } diff --git a/src/controllers/subscriptions.types.ts b/src/controllers/subscriptions.types.ts index 15cd8b5..8246c72 100644 --- a/src/controllers/subscriptions.types.ts +++ b/src/controllers/subscriptions.types.ts @@ -10,14 +10,7 @@ export type SubscriptorData = { port: string, endpoint: string, secretkey: string, - method: "POST" | "GET" | "PUT" | "DELETE" - open: Date, - options?: { - /* En ms. Cada cuanto se envia un mensaje nuevo, para solo se envia un mensaje */ - period?: number, - /* Numero de mensajes, para undefiend solo se manda uno, para <= 0 seran infinitos */ - mesages?: number, - } + method: "POST" | "PUT" | "DELETE" } export type ShopifyEvent = { @@ -33,3 +26,9 @@ export type Topic = string export type SetupSubscription = SubscriptorData & { topic: string } + +export type ScheduledEvent = { + topic: string // Meter una lista de topics/plantilla + numberOfMessages?: number, + periodMs?: number +} diff --git a/src/routes/webhook.ts b/src/routes/webhook.ts index 06265b0..1862dc5 100644 --- a/src/routes/webhook.ts +++ b/src/routes/webhook.ts @@ -1,21 +1,25 @@ import { Router } from 'express'; import { ordersHandlerBuilder } from '#controllers/orders.webhook.js'; import { subscriptonHandlerBuilder } from '#controllers/subscriptions.js'; -import { generateSubscriptions } from '#config/initial_hosts.js'; +import { generateSubscriptions, INITIAL_EVENTS, INITIAL_HOSTS } from '#config/initial_hosts.js'; import { EventScheduler, SubscriptionManager } from '#controllers/subscription_manager.js'; const webhookRouter = Router(); -const baseSubscriptions = generateSubscriptions() -const subscriptionList = [...baseSubscriptions.values()].map(e => e.subscriptors).flat() -const scheduler = new EventScheduler({ events: subscriptionList }) -const subscriptions = new SubscriptionManager(scheduler, baseSubscriptions) +const initialSubscriptions = generateSubscriptions() +const eventosIniciales = INITIAL_EVENTS + +const subscriptionsManager = new SubscriptionManager(initialSubscriptions) +const scheduler = new EventScheduler({ + events: eventosIniciales, + subscriptionManager: subscriptionsManager +}) // subto -webhookRouter.post('/subto', subscriptonHandlerBuilder(subscriptions)); +webhookRouter.post('/subto', subscriptonHandlerBuilder(subscriptionsManager)); // Simulacion de los webhook de shopify // Al llamar se supone que se genera el evento -webhookRouter.post('/shopify/orders', ordersHandlerBuilder(subscriptions)); +webhookRouter.post('/shopify/orders', ordersHandlerBuilder(subscriptionsManager)); export default webhookRouter; diff --git a/src/shared/requests.ts b/src/shared/requests.ts index a1316bb..44ed828 100644 --- a/src/shared/requests.ts +++ b/src/shared/requests.ts @@ -11,7 +11,8 @@ export function requestBuilder(args: { const request = http.request({ host: args.host, port: args.port, - path: args.endpoint + path: args.endpoint, + method: args.method }) Object.entries(args.headers).forEach(([name, value]) => {