Skip to content

Conference Management (for devs)

Vincent edited this page Feb 15, 2022 · 3 revisions

Conference Management is the heart of Strive: The entire logic of the features of a conference are managed here. It is responsible for synchronizing participants, handling permissions and managing connections.

Important Design Choices

Mediator Pattern

In Strive we use the Mediator pattern to execute commands and publish events. MediatR is the library used to define the mediator.

Dependency Injection (DI)

Autofac is used as dependency injection container. Every project contains a Module class in the main directory which registers the services provided by this class.

Logging

Logging is handled by Microsoft.Extensions.Logging.Abstractions, which is currently implemented by Serilog.

No state except in repositories

As it should be possible to use Strive with load balancing, do not keep any state in instances. Use the key value repositories for temporary state and the database to persist objects. Some applies for timers, locks, etc.

Structure

The conference management is split into three main projects:

  • Strive (presentation layer)
  • Strive.Core (business layer)
  • Strive.Infrastructure (infrastructure layer)

As Strive is using the Onion Architecture, Strive.Core doesn't have any dependencies on the "outside" and should be as library agnostic as possible. This includes database implementations.

Business Layer (Strive.Core)

Directories:

  • /Domain includes entities that are important to many different services. The most important class is Conference, which is used by most services and includes very basic information about a conference (which is also persisted in a database)
  • /Dto includes dtos that are important to many different services. Error is the most important class here at the moment and is used as a base class to report errors to the user interface
  • /Errors implements different error types. The types are similar to the HTTP status codes (so we can map them easily when responding the error). The name of the errors should be descriptive.
  • /Extensions some common extensions
  • /Interfaces basicaly dependencies to the outside that must be implemented somehow (as they are injected using DI)
  • /Services this folder contains the specific features Strive offers. More information provided below
  • /Specifications used to query the database using Linq
  • /Utilities some utilities used by multiple services
  • CoreModule the Autofac module to register the classes of this project

Strive Services

All features of Strive (chat, polls, rooms, etc.) are structured in services which can also have dependencies (but that should all be handled by the Mediator pattern).

Typically, a service contains these folders:

  • /Gateways repositories to store data (usually implementing IStateRepository). These repositories are implemented by the infrastructure layer.
  • /NotificationHandlers mediator handlers for notifications including common ones like ConferenceOpenedNotification, ParticipantJoinedNotification etc.
  • /Notifications mediator notifications provided by this service
  • /Requests mediator requests for this service (actions)
  • /UseCases mediator handlers for requests from the /Requests folder

Additionally, there are some standard files:

  • <ServiceName>Error defines errors thrown by this service
  • Synchronized<ServiceName> and Synchronized<ServiceName>Provider are for state synchronization (more info below)
Synchronization

A special service is Synchronization which provides an easy to use interface to synchronize objects to a specific group of participants. First of all, you have to define a simple DTO class (a POCO), that just keeps the information you want to synchronize (records are an amazing choice here).

Then, you have to define a ISynchronizedObjectProvider that has the following interface:

Type Type { get; }
string Id { get; }
ValueTask<object> FetchValue(string conferenceId, SynchronizedObjectId synchronizedObjectId);
ValueTask<IEnumerable<SynchronizedObjectId>> GetAvailableObjects(Participant participant);

The Type must be assigned to the DTO class you just created. The Id must be a unique identifier for the object type (which is read by the frontend). GetAvailableObjects returns the object ids a participant may access. There may be multiple instances of an object within a conference (for example every participant has its own permissions), so in turn to have unique object ids, you can include the participant id in the returned object id (of the specific participant). Also, it is possible to check for admin rights here and return permissions objects of all participants if the requesting user is an admin. Of course there may also be only one instance that can be accessed by everyone, so you can just return the Id.

FetchValue fetches the value of an object. Caching etc. is managed by the framework. Please make sure that the value can always be fetched.

For simplication, there exists the SynchronizedObjectProvider<T> class which automatically fills the Type and SynchronizedObjectProviderForAll<T> which returns the same object id for every participant (when you only have a single instance for everyone).

SynchronizedObjectProvider<T> is automatically registered in the DI Container, but you cannot keep any state as a new instance may be created or the same provider may be reused for different conferences. Use repositories for that.

Infrastructure Layer (Strive.Infrastructure)

This layer connects the business layer to actual implementations of services (databases, etc.).

Directories:

  • Auth services for authentication
  • Data classes for persistence, currently implemented by MongoDB
  • Extensions some extensions used in the infrastructure layer
  • KeyValue implementation of state repositories, currently implemented by Redis (actually, there is another abstraction for integration tests)
  • Scheduler used for scheduling notifications (for timers etc.)
  • Serialization important classes for Json and Bson serialization for some objects
  • Sfu some classes to handle the connection to the SFU
  • Utilities some utilities used in the infrastructure and presentation layer

Presentation layer (Strive)

Directories:

  • Auth provides utilities for authentication
  • Config configuration classes for serveral services
  • Controllers Http Api
  • Extensions extensions for the presentation layer
  • Hubs SignalR Hubs used for real time communication
  • Messaging handlers for RabbitMQ MassTransit
  • Models DTOs for http requests and responses including validators
  • Presenters used to map data from databases to dtos for users
  • Services basic services for the presentation layer
  • Utilities basic utilities for the presentation layer