Snapi Architecture Overview

TeamSnap

Dustin McCraw

June 2018

Architecture

Data Stores

  1. teamsnap_production
  2. Redis

Services

  1. McFeely
  2. Dozer
  3. Walle
  4. ....

Core

  1. Apiv3/Snapi
  2. Classic

Clients

  1. Nextjenn
  2. League Frontend
  3. iOS
  4. Android

Message Broker

  1. RabbitMQ

teamsnap_production/ ecco

  • Maria DB
  • Migrations managed through Ecco
  • Ecco is Ruby project
  • bundle exec rake generate:migration[some_name]
  • bin/setup
https://github.com/teamsnap/ecco

redis

  • In-memory data structure store
  • NoSql key value store
  • Use to store across apps
    • rollouts
    • background job information
    • rate limiting
    • etc...

REmote Dictionary Server

Classic

  • Rails 2
  • Ruby 2.1.2
  • Original product
  • First Commit: May 25, 2007
  • The app most of our customers land on
  • Embeds our two frontend technologies
    • Nextjenn
    • League Frontend
  • bin/setup
https://github.com/teamsnap/classic

Classic

bundle exec foreman start
bundle exec thin start -p 3001
bundle exec unicorn -p 3001

 

script/console
https://github.com/teamsnap/classic

Running locally:

Apiv3/Snapi

  • "Source of Truth"
  • Sinatra App
  • Ruby 2.3
  • Uses sequel gem for db access
  • Uses Collection+JSON serialization
  • bin/setup

Authentication methods:

  • Bearer Token (user)
  • HMAC (services)
  • SSO
https://github.com/teamsnap/apiv3

Apiv3

bundle exec foreman start
bundle exec rails s

 

bundle exec rails c

Running locally:

Classic running Resque

Handles background tasks

bundle exec foreman start
​bundle exec rake environment resque:work QUEUE=*

Running locally:

Resque.enqueue(Worker, params)

 

class Worker
@queue = :normal

Apiv3 running Sidekiq

Handles background tasks

bundle exec foreman start
​bundle exec sidekiq -L log/sidekiq.log

Running locally:

Worker.perform_async

 

include Sidekiq::Worker
def perform()

RabbitMQ

message broker

Message
  • topic
  • message_type
  • values

Microservices Architecture

  1. Loosely coupled services, each which implements their own business logic.
  2. Allows for scaling and decoupling of concerns at the cost of complexity.
  3. Use RabbitMQ to pass messages between services.

RabbitMQ

http://localhost:15672/#/queues

guest/guest

RabbitMQ

http://localhost:15672/#/queues

guest/guest

McFeely

  • Emque Service
  • Listens on RabbitMq for messages
  • Requests data from Apiv3
  • Sends out our emails
bundle exec emque -d start 
bundle exec emque start
bundle exec emque stop

* -d runs a deamon background version, need to use the stop command

Running locally:

Dozer

  • Emque Service
  • Listens on RabbitMq for messages
  • Requests data from Apiv3
  • Sends out our push notifications
bundle exec emque -d start 
bundle exec emque start
bundle exec emque stop

 

* -d runs a deamon background version, need to use the stop command

Running locally:

Walle

  • Emque Service
  • Listens on RabbitMq for messages
  • Pushes data up into our ElasticSearch
bundle exec emque -d start 
bundle exec emque start
bundle exec emque stop

 

* -d runs a deamon background version, need to use the stop command

Running locally:

Nextjenn

  • Javascript frontend
  • Custom Chip framework
  • Embedded in Classic
  • Displays team side ui
  • Moving to using React/Redux

 

brunch watch --server

Running locally:

https://github.com/teamsnap/nextjenn-web

League Frontend

  • Javascript React/Redux
  • Embedded in Classic
  • Displays some league side ui
npm run start

http::/localhost:6543

Running locally:

https://github.com/teamsnap/league-frontend

Follow an Email

  1. User navigates to classic
  2. Classic loads either Nextjenn/League Frontend
  3. Frontend hits Apiv3 with email data
  4. Apiv3 stores data in production_db
  5. Apiv3 creates a background job
  6. Apiv3/Sideqik picks up background job to create more database entries and produces RabbitMQ messages
  7. McFeely consumes the message and sends the email. 

Thank you!

Made with Slides.com