Skip to content

decentraland/social-service-ea

Repository files navigation

EA Social Service

Coverage Status

A microservice that handles social interactions (friendships) for Decentraland, built using the Well Known Components architecture pattern.

Table of Contents

🌟 Features

  • Friendship management (requests, accepts, rejects, cancellations)
  • Real-time friend status updates
  • Mutual friends discovery
  • Online status tracking
  • Integration with Archipelago for peer synchronization

🏗 Architecture

Component-Based Architecture

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

Database Design

@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

Flow Diagrams

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
Loading

🚀 Getting Started

Prerequisites

  • Node.js v18.20.4
  • Docker and Docker Compose
  • PostgreSQL
  • Redis

Local Development

  1. Clone the repository
  2. Install dependencies:
yarn install
  1. Start the development environment:
docker-compose up -d
  1. Run migrations:
yarn migrate up
  1. Run the service:
yarn start

Environment Variables

Key environment variables needed:

  • REDIS_HOST: URL of the Redis instance
  • PG_COMPONENT_PSQL_CONNECTION_STRING: URL of the PostgreSQL instance
  • ARCHIPELAGO_STATS_URL: URL of the Archipelago Stats service

See .env.default for all available options.

🧪 Testing

The project uses Jest for testing. Run tests with:

yarn test

Test Coverage

Coverage reports are generated in the /coverage directory and uploaded to Coveralls.

🔄 CI/CD

The project uses GitHub Actions for:

  • Continuous Integration
  • Docker image building
  • Automated deployments to dev/prod environments
  • Dependency management with Dependabot

Deployment Environments

  • Development: Automatic deployments on main branch
  • Production: Manual deployments via GitHub releases