A microservice that handles social interactions (friendships) for Decentraland, built using the Well Known Components architecture pattern.
- Friendship management (requests, accepts, rejects, cancellations)
- Real-time friend status updates
- Mutual friends discovery
- Online status tracking
- Integration with Archipelago for peer synchronization
This service follows the Well Known Components pattern, where each component is a self-contained unit with a clear interface. The main components are:
- Database (PostgreSQL): Stores friendship relationships and actions
- Cache (Redis): Handles temporary data and real-time status
- RPC Server: Manages client-server RPC communication
- PubSub: Handles real-time updates
- Archipelago Stats: Integrates with Decentraland's peer discovery system
- Peer Tracking: Monitors online status of users through the NATS messaging system
- Peers Synchronization: Synchronizes peers with the Archipelago Stats service and store them in Redis
@startuml
!define table(x) class x << (T,#FFAAAA) >>
!define primary_key(x) <u>x</u>
!define foreign_key(x) #x#
hide methods
hide stereotypes
table(friendships) {
primary_key(id): uuid
address_requester: varchar
address_requested: varchar
is_active: boolean
created_at: timestamp
updated_at: timestamp
--
indexes
..
hash(address_requester)
hash(address_requested)
btree(LOWER(address_requester))
btree(LOWER(address_requested))
}
table(friendship_actions) {
primary_key(id): uuid
foreign_key(friendship_id): uuid
action: varchar
acting_user: varchar
metadata: jsonb
timestamp: timestamp
--
indexes
..
btree(friendship_id)
}
friendships ||--|{ friendship_actions
@enduml
The database schema supports:
- Bidirectional friendships
- Action history tracking
- Metadata for requests
- Optimized queries with proper indexes
See migrations for details: migrations
sequenceDiagram
participant Client
participant WebSocket
participant RPC Server
participant Redis
participant NATS
participant DB
Note over Client,DB: Connection Setup
Client->>WebSocket: WS Handshake
activate WebSocket
WebSocket-->>Client: Connection Established
Client->>WebSocket: Auth Message
WebSocket->>RPC Server: Attach Transport
activate RPC Server
Note over RPC Server,NATS: Subscriptions Setup
RPC Server->>Redis: Subscribe to updates channels
activate Redis
Note over Redis: friendship.updates
Note over Redis: friend.status.updates
RPC Server->>NATS: Subscribe to peer events
activate NATS
Note over NATS: peer.*.connected
Note over NATS: peer.*.disconnected
Note over NATS: peer.*.heartbeat
Note over Client,DB: Friendship Request Flow
Client->>RPC Server: Friend Request
RPC Server->>DB: Create Friendship Record
DB-->>RPC Server: Friendship Created
RPC Server->>DB: Record Friendship Action
RPC Server->>Redis: Publish Friendship Update
RPC Server-->>Client: Request Confirmation
Note over Client,DB: Friendship Updates Flow
Redis-->>RPC Server: Friendship Update Event
RPC Server-->>Client: Stream Friendship Updates
Note over RPC Server: (accept/cancel/reject/delete)
Note over Client,DB: Friends Lifecycle
NATS-->>Redis: Peer Heartbeat
Redis-->>RPC Server: Friend Status Update
RPC Server->>Redis: Request Cached Peers
Redis-->>RPC Server: Cached Peers
RPC Server->>DB: Request Online Friends
DB-->>RPC Server: Online Friends
RPC Server->>DB: Query Online Friends
RPC Server-->>Client: Stream Friend Status Updates
Note over RPC Server: (online/offline)
Note over Client,DB: Cleanup
Client->>WebSocket: Connection Close
WebSocket->>RPC Server: Detach Transport
RPC Server->>Redis: Unsubscribe
RPC Server->>NATS: Unsubscribe
deactivate WebSocket
deactivate RPC Server
deactivate Redis
deactivate NATS
- Node.js v18.20.4
- Docker and Docker Compose
- PostgreSQL
- Redis
- Clone the repository
- Install dependencies:
yarn install
- Start the development environment:
docker-compose up -d
- Run migrations:
yarn migrate up
- Run the service:
yarn start
Key environment variables needed:
REDIS_HOST
: URL of the Redis instancePG_COMPONENT_PSQL_CONNECTION_STRING
: URL of the PostgreSQL instanceARCHIPELAGO_STATS_URL
: URL of the Archipelago Stats service
See .env.default
for all available options.
The project uses Jest for testing. Run tests with:
yarn test
Coverage reports are generated in the /coverage
directory and uploaded to Coveralls.
The project uses GitHub Actions for:
- Continuous Integration
- Docker image building
- Automated deployments to dev/prod environments
- Dependency management with Dependabot
- Development: Automatic deployments on main branch
- Production: Manual deployments via GitHub releases