This repository has been archived by the owner on Nov 22, 2023. It is now read-only.
generated from well-known-components/template-server
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: implement archipelago with NATS
- Loading branch information
Juan Scolari
committed
Apr 11, 2022
1 parent
48d7079
commit 8be9724
Showing
11 changed files
with
144 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { IslandUpdates, PeerPositionChange } from "@dcl/archipelago" | ||
import { JSONCodec } from "nats" | ||
import { GlobalContext } from "../types" | ||
|
||
const jsonCodec = JSONCodec() | ||
|
||
export function setupTopics(globalContext: GlobalContext): void { | ||
const messageBroker = globalContext.components.messageBroker | ||
const archipelago = globalContext.components.archipelago | ||
|
||
messageBroker.subscribe("heartbeat", (data: Uint8Array) => { | ||
const peerPositionChange = jsonCodec.decode(data) as PeerPositionChange | ||
archipelago.setPeersPositions(peerPositionChange) | ||
}) | ||
|
||
archipelago.subscribeToUpdates((updates: IslandUpdates) => { | ||
if (Object.keys(updates).length) { | ||
messageBroker.publish("island_updates", updates) | ||
} | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { ArchipelagoController, defaultArchipelagoController } from "@dcl/archipelago" | ||
import { IConfigComponent } from "@well-known-components/interfaces" | ||
|
||
export declare type IArchipelagoComponent = ArchipelagoController | ||
|
||
export declare type ArchipelagoComponents = { | ||
config: IConfigComponent | ||
} | ||
|
||
export async function createArchipelagoComponent(components: ArchipelagoComponents): Promise<ArchipelagoController> { | ||
const { config } = components | ||
|
||
const flushFrequency = await config.requireNumber("ARCHIPELAGO_FLUSH_FREQUENCY") | ||
const joinDistance = await config.requireNumber("ARCHIPELAGO_JOIN_DISTANCE") | ||
const leaveDistance = await config.requireNumber("ARCHIPELAGO_LEAVE_DISTANCE") | ||
const maxPeersPerIsland = await config.requireNumber("ARCHIPELAGO_MAX_PEERS_PER_ISLAND") | ||
|
||
const controller = defaultArchipelagoController({ | ||
flushFrequency, | ||
archipelagoParameters: { | ||
joinDistance, | ||
leaveDistance, | ||
maxPeersPerIsland, | ||
}, | ||
}) | ||
|
||
return controller | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,64 +1,81 @@ | ||
import { IConfigComponent, ILoggerComponent } from "@well-known-components/interfaces" | ||
import { connect, JSONCodec } from "nats" | ||
import { IBaseComponent, IConfigComponent, ILoggerComponent } from "@well-known-components/interfaces" | ||
import { connect, JSONCodec, StringCodec, NatsConnection, Subscription } from "nats" | ||
import { BaseComponents } from "../types" | ||
|
||
export declare type IMessageBrokerComponent = { | ||
publish(subject: string, message: any): void | ||
subscribe(subject: string, handler: Function, respond?: boolean): void | ||
} | ||
publish(topic: string, message: any): void | ||
subscribe(topic: string, handler: Function): Subscription | ||
|
||
export declare type MessageBrokerComponents = { | ||
config: IConfigComponent | ||
logs: ILoggerComponent | ||
start(): Promise<void> | ||
stop(): Promise<void> | ||
} | ||
|
||
export async function createMessageBrokerComponent( | ||
components: MessageBrokerComponents | ||
): Promise<IMessageBrokerComponent> { | ||
components: Pick<BaseComponents, "config" | "logs"> | ||
): Promise<IMessageBrokerComponent & IBaseComponent> { | ||
const { config, logs } = components | ||
const logger = logs.getLogger("MessageBroker") | ||
const jsonCodec = JSONCodec() | ||
const stringCodec = StringCodec() | ||
|
||
// config | ||
const port = await config.requireNumber("NATS_SERVER_PORT") | ||
const host = await config.requireString("NATS_SERVER_HOST") | ||
|
||
const serverConfig = { servers: `${host}:${port}` } | ||
const server = await connect(serverConfig) | ||
const natsUrl = (await config.getString("NATS_URL")) || "nats.decentraland.zone:4222" | ||
const natsConfig = { servers: `${natsUrl}` } | ||
let natsConnection: NatsConnection | ||
|
||
const publish = (subject: string, message: any) => { | ||
server.publish(subject, jsonCodec.encode(message)) | ||
function publish(topic: string, message: any): void { | ||
if (message instanceof Uint8Array) { | ||
natsConnection.publish(topic, message) | ||
} else if (typeof message === "object") { | ||
natsConnection.publish(topic, jsonCodec.encode(message)) | ||
} else if (typeof message === "string") { | ||
natsConnection.publish(topic, stringCodec.encode(message)) | ||
} else { | ||
logger.error(`Invalid message: ${JSON.stringify(message)}`) | ||
} | ||
} | ||
|
||
const subscribe = (subject: string, handler: Function, respond?: boolean) => { | ||
const subscription = server.subscribe(subject) | ||
function subscribe(topic: string, handler: Function): Subscription { | ||
const subscription = natsConnection.subscribe(topic) | ||
;(async () => { | ||
for await (const message of subscription) { | ||
try { | ||
if (message.data.length) { | ||
const data = jsonCodec.decode(message.data) as any | ||
logger.debug(`[${subscription.getProcessed()}]: ${message.subject}: ${JSON.stringify(data, null, 2)}`) | ||
const data = message.data | ||
const payload = await handler(data) | ||
if (respond) { | ||
message.respond(jsonCodec.encode(payload)) | ||
} | ||
} else { | ||
logger.debug(`[${subscription.getProcessed()}]: ${message.subject}`) | ||
const payload = await handler() | ||
if (respond) { | ||
message.respond(jsonCodec.encode(payload)) | ||
} | ||
} | ||
} catch (err: any) { | ||
logger.error(err) | ||
} | ||
} | ||
})() | ||
return subscription | ||
} | ||
|
||
async function start() { | ||
try { | ||
natsConnection = await connect(natsConfig) | ||
logger.info(`Connected to NATS: ${natsUrl}`) | ||
} catch (error) { | ||
logger.error(`An error occurred trying to connect to the NATS server: ${natsUrl}`) | ||
throw error | ||
} | ||
} | ||
|
||
const nats: IMessageBrokerComponent = { | ||
async function stop() { | ||
try { | ||
await natsConnection.close() | ||
} catch (error) { | ||
logger.error(`An error occurred trying to close the connection to the NATS server: ${natsUrl}`) | ||
} | ||
} | ||
|
||
return { | ||
publish, | ||
subscribe, | ||
start, | ||
stop, | ||
} | ||
|
||
return nats | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters