Skip to content

Commit 340c173

Browse files
committed
feat: report profiles and scenes updates to NATS
1 parent b2c0a18 commit 340c173

9 files changed

Lines changed: 288 additions & 12 deletions

File tree

.env.default

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ REGISTRY_URL=<URL>
1717
ASSET_BUNDLE_ADMIN_URL=<URL>
1818
PROFILE_IMAGES_URL=<URL>
1919

20+
# NATS
21+
NATS_URL=
22+
2023
# Sync
2124
DISABLE_PROFILE_SYNC=true
2225

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"@dcl/memory-queue-component": "^2.0.0",
3535
"@dcl/pg-component": "^0.1.0",
3636
"@dcl/platform-crypto-middleware": "^1.1.0",
37+
"@dcl/protocol": "https://sdk-team-cdn.decentraland.org/@dcl/protocol/branch//dcl-protocol-1.0.0-22239310034.commit-1571733.tgz",
3738
"@dcl/schemas": "^24.0.0",
3839
"@dcl/snapshots-fetcher": "^9.2.2",
3940
"@dcl/sqs-component": "^2.0.4",
@@ -43,6 +44,7 @@
4344
"@well-known-components/interfaces": "^1.4.3",
4445
"@well-known-components/logger": "^3.1.3",
4546
"@well-known-components/metrics": "^2.1.0",
47+
"@well-known-components/nats-component": "^2.0.0",
4648
"bloom-filters": "^3.0.4",
4749
"dcl-catalyst-client": "^21.10.3",
4850
"lru-cache": "9.1.2",

src/components.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ import { createPointerChangesHandlerComponent } from './logic/sync/pointer-chang
3737
import { createSynchronizerComponent } from './logic/sync/synchronizer'
3838
import { createOwnershipValidatorJob } from './logic/sync/ownership-validator-job'
3939
import { createCoordinatesComponent } from './logic/coordinates'
40+
import { createConfigComponent } from '@well-known-components/env-config-provider'
41+
import { createNatsComponent } from '@well-known-components/nats-component'
4042

4143
// Initialize all the components of the app
4244
export async function initComponents(): Promise<AppComponents> {
@@ -116,11 +118,14 @@ export async function initComponents(): Promise<AppComponents> {
116118
config
117119
})
118120
const catalyst = await createCatalystAdapter({ logs, fetch, config })
121+
const natsLogs = await createLogComponent({ config: createConfigComponent({ LOG_LEVEL: 'WARN' }) })
122+
const nats = await createNatsComponent({ config, logs: natsLogs })
119123
const entityPersister = createEntityPersisterComponent({
120124
logs,
121125
db,
122126
profilesCache,
123-
entityDeploymentTracker
127+
entityDeploymentTracker,
128+
nats
124129
})
125130
const profileRetriever = createProfileRetrieverComponent({
126131
logs,
@@ -204,7 +209,8 @@ export async function initComponents(): Promise<AppComponents> {
204209
coordinates,
205210
db,
206211
logs,
207-
config
212+
config,
213+
nats
208214
})
209215
const messageConsumer = createMessagesConsumerComponent({
210216
logs,
@@ -243,6 +249,7 @@ export async function initComponents(): Promise<AppComponents> {
243249
snapshotsHandler,
244250
pointerChangesHandler,
245251
synchronizer,
246-
ownershipValidatorJob
252+
ownershipValidatorJob,
253+
nats
247254
}
248255
}

src/logic/handlers/deployment-handler.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,18 @@ import { Entity } from '@dcl/schemas'
22
import { AppComponents, IEventHandlerComponent, EventHandlerName, EventHandlerResult, Registry } from '../../types'
33
import { DeploymentToSqs } from '@dcl/schemas/dist/misc/deployments-to-sqs'
44
import { Authenticator } from '@dcl/crypto'
5+
import { SceneUpdateNotification } from '@dcl/protocol/out-js/decentraland/kernel/comms/v3/archipelago.gen'
56

67
export const createDeploymentEventHandler = ({
78
registry,
89
catalyst,
910
worlds,
1011
db,
11-
logs
12+
logs,
13+
nats
1214
}: Pick<
1315
AppComponents,
14-
'catalyst' | 'worlds' | 'db' | 'logs' | 'registry'
16+
'catalyst' | 'worlds' | 'db' | 'logs' | 'registry' | 'nats'
1517
>): IEventHandlerComponent<DeploymentToSqs> => {
1618
const HANDLER_NAME = EventHandlerName.DEPLOYMENT
1719
const logger = logs.getLogger('deployment-handler')
@@ -77,6 +79,25 @@ export const createDeploymentEventHandler = ({
7779
versions: defaultVersions
7880
})
7981

82+
// Publish scene update notification for non-world deployments
83+
if (!worlds.isWorldDeployment(event) && entity.pointers?.length > 0) {
84+
try {
85+
nats.publish(
86+
'service.scene_update',
87+
SceneUpdateNotification.encode({
88+
sceneId: entity.id,
89+
parcels: entity.pointers,
90+
timestamp: entity.timestamp
91+
}).finish()
92+
)
93+
} catch (err: any) {
94+
logger.warn('Failed to publish scene update notification', {
95+
sceneId: entity.id,
96+
error: err.message
97+
})
98+
}
99+
}
100+
80101
return { ok: true, handlerName: HANDLER_NAME }
81102
} catch (error: any) {
82103
logger.error('Failed to process', {

src/logic/message-processor.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,11 @@ export async function createMessageProcessorComponent({
3030
coordinates,
3131
db,
3232
logs,
33-
config
33+
config,
34+
nats
3435
}: Pick<
3536
AppComponents,
36-
'catalyst' | 'worlds' | 'registry' | 'queuesStatusManager' | 'db' | 'logs' | 'config' | 'coordinates'
37+
'catalyst' | 'worlds' | 'registry' | 'queuesStatusManager' | 'db' | 'logs' | 'config' | 'coordinates' | 'nats'
3738
>): Promise<IMessageProcessorComponent> {
3839
const MAX_RETRIES: number = (await config.getNumber('MAX_RETRIES')) || 3
3940
const log = logs.getLogger('message-processor')
@@ -45,7 +46,7 @@ export async function createMessageProcessorComponent({
4546
| WorldUndeploymentEvent
4647
| WorldSpawnCoordinateSetEvent
4748
>[] = [
48-
createDeploymentEventHandler({ catalyst, worlds, registry, db, logs }),
49+
createDeploymentEventHandler({ catalyst, worlds, registry, db, logs, nats }),
4950
createTexturesEventHandler({
5051
db,
5152
logs,

src/logic/sync/entity-persister.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import PQueue from 'p-queue'
22
import { AppComponents, IEntityPersisterComponent } from '../../types'
33
import { Sync } from '../../types'
44
import { Entity } from '@dcl/schemas'
5+
import { ProfileUpdateNotification } from '@dcl/protocol/out-js/decentraland/kernel/comms/v3/archipelago.gen'
56

67
const DB_PERSISTENCE_CONCURRENCY = 30
78

@@ -20,8 +21,9 @@ export function createEntityPersisterComponent({
2021
logs,
2122
db,
2223
profilesCache,
23-
entityDeploymentTracker
24-
}: Pick<AppComponents, 'logs' | 'db' | 'profilesCache' | 'entityDeploymentTracker'>): IEntityPersisterComponent {
24+
entityDeploymentTracker,
25+
nats
26+
}: Pick<AppComponents, 'logs' | 'db' | 'profilesCache' | 'entityDeploymentTracker' | 'nats'>): IEntityPersisterComponent {
2527
const logger = logs.getLogger('entity-persistent')
2628

2729
let bootstrapComplete = false
@@ -43,6 +45,23 @@ export function createEntityPersisterComponent({
4345
// mark as processed in bloom filter (permanent tracking)
4446
entityDeploymentTracker.markAsProcessed(entity.id)
4547

48+
// publish profile update notification to NATS
49+
try {
50+
nats.publish(
51+
'service.profile_update',
52+
ProfileUpdateNotification.encode({
53+
address: entity.pointers[0],
54+
profileJson: JSON.stringify(entity),
55+
timestamp: entity.timestamp
56+
}).finish()
57+
)
58+
} catch (err: any) {
59+
logger.warn('Failed to publish profile update notification', {
60+
address: entity.pointers[0],
61+
error: err.message
62+
})
63+
}
64+
4665
const dbEntity: Sync.ProfileDbEntity = {
4766
...entity,
4867
pointer: entity.pointers[0],

src/types/system.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import {
3030
import { metricDeclarations } from '../metrics'
3131
import { IContentStorageComponent } from '@dcl/catalyst-storage'
3232
import { ICoordinatesComponent, SpawnCoordinate } from '../logic/coordinates'
33+
import { INatsComponent } from '@well-known-components/nats-component/dist/types'
3334

3435
export type GlobalContext = {
3536
components: BaseComponents
@@ -71,6 +72,7 @@ export type AppComponents = BaseComponents & {
7172
pointerChangesHandler: IProfilesSynchronizerComponent
7273
failedProfilesRetrier: IFailedProfilesRetrierComponent
7374
ownershipValidatorJob: IBaseComponent
75+
nats: INatsComponent
7476
}
7577

7678
// components used in tests

test/components.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { createCoordinatesComponent } from '../src/logic/coordinates'
1919
import { createQueuesStatusManagerComponent } from '../src/logic/queues-status-manager'
2020
import { createInMemoryCacheComponent } from '../src/adapters/memory-cache'
2121
import { createWorldsMockComponent } from './unit/mocks/worlds'
22+
import { INatsComponent } from '@well-known-components/nats-component/dist/types'
2223

2324
/**
2425
* Behaves like Jest "describe" function, used to describe a test for a
@@ -64,6 +65,14 @@ async function initComponents(): Promise<TestComponents> {
6465
const memoryStorage = createInMemoryCacheComponent()
6566
const queuesStatusManager = createQueuesStatusManagerComponent({ memoryStorage })
6667

68+
// Create a mock NATS component for tests
69+
const nats: INatsComponent = {
70+
publish: () => {},
71+
subscribe: () => ({ unsubscribe: () => {} }),
72+
start: async () => {},
73+
stop: async () => {}
74+
} as unknown as INatsComponent
75+
6776
// Create message processor for integration tests
6877
// Uses the real catalyst from originalInitComponents() so that jest.spyOn works
6978
// consistently for both HTTP handler tests and message processor tests.
@@ -75,7 +84,8 @@ async function initComponents(): Promise<TestComponents> {
7584
coordinates,
7685
db,
7786
logs,
78-
config
87+
config,
88+
nats
7989
})
8090

8191
const messageConsumer = createMessageConsumerMockComponent()
@@ -88,6 +98,7 @@ async function initComponents(): Promise<TestComponents> {
8898
coordinates,
8999
registry,
90100
metrics,
101+
nats,
91102
localFetch: await createLocalFetchCompoment(config),
92103
messageConsumer,
93104
messageProcessor,

0 commit comments

Comments
 (0)