Tech Overview
6/23/17
TeamSnap
Tech
- Classic
- Apiv3
- Nextjenn
- League Frontend
- McFeely
- Dozer
- Walle
- Other small services
Classic
- Rails 2
- Ruby 2.1.2
- Original product
- Still the landing page for most of our customer face
- Embeds our two frontend technologies
- Nextjenn
- League Frontend
Apiv3
- Sinatra App
- Ruby 2.3
- Uses sequel gem for db access
- Uses Collection+JSON
- TeamSnap's single source of truth
Has two forms of authentication:
- Bearer Token (user)
- HMAC (services)
Nextjenn
- Javascript frontend
- Custom Chip framework
- Embedded in Classic
- Displays team side ui
- Moving to using React/Redux
League Frontend
- Javascript React/Redux
- Embedded in Classic
- Displays some league side ui
McFeely
- Emque Service
- Listens on RabbitMq for messages
- Requests data from Apiv3
- Sends out our emails
Dozer
- Emque Service
- Listens on RabbitMq for messages
- Requests data from Apiv3
- Sends out our push notifications
Walle
- Emque Service
- Listens on RabbitMq for messages
- Pushes data up into our ElasticSearch cluster on cloud.elastic.co
Collection+JSON
Collection+JSON is a JSON-based read/write hypermedia-type designed to support management and querying of simple collections.
It uses a JSON structure to contains things like collections, refs, templates, queries, and commands.
https://github.com/collection-json/spec
apiv3 base_collection
Returned for every request. Contains:
-
version -- the current version of the api
-
href -- href of this collection
-
rel -- unique identifier
-
template -- for creating/updating
-
links -- associated links
-
queries -- list of queries
-
commands -- list of commands
class ContactSerializer < Scribe
private
def base_collection
{
collection: {
version: API_VERSION,
href: contacts_url,
rel: "contacts",
template: {
data: [
{name: "label", value: nil},
{name: "type", value: Contact.type}
]
},
links: [
{rel: "contact_email_addresses", href: contact_email_addresses_url},
{rel: "self", href: request_url}
],
queries: [
{
rel: "search",
href: search_contacts_url,
data: [
{name: "team_id", value: nil},
{name: "can_receive_push_notifications", value: nil}
]
}
],
commands: [
{
rel: "create_bulk_contacts",
href: create_bulk_contacts_contacts_url,
data: [
{name: "team_id", value: nil},]
]
}
]
}
}
end
end
apiv3 as_item
Called for every item in response.collection.
-
href -- href of this collection
-
data -- data for the item
-
links -- associated links
class ContactSerializer < Scribe
private
def as_item(object)
{
href: contact_url(object.id),
data: [
{name: "id", value: object.id},
{name: "type", value: object.type},
{name: "address_city", value: object.address_city},
{name: "address_country", value: object.address_country},
{name: "address_state", value: object.address_state},
{name: "address_street1", value: object.address_street1},
{name: "address_street2", value: object.address_street2},
{name: "address_zip", value: object.address_zip}
{name: "created_at", value: object.created_at, type: "DateTime"},
{name: "updated_at", value: object.updated_at, type: "DateTime"},
],
links: [
{
rel: "contact_email_addresses",
href: search_contact_email_addresses_url(:contact_id => object.id)
},
{
rel: "contact_phone_numbers",
href: search_contact_phone_numbers_url(:contact_id => object.id)
},
{rel: "member", href: member_url(object.member_id)},
]
}
end
end
{
"collection": {
"version": "3.454.0",
"href": "http://localhost:3000/contacts",
"rel": "contacts",
"template": {
"data": [
{
"name": "label",
"value": null
},
{
"name": "address_street1",
"value": null
},
...
{
"name": "type",
"value": "contact"
}
]
},
"links": [
{
"rel": "contact_email_addresses",
"href": "http://localhost:3000/contact_email_addresses"
},
....
{
"rel": "self",
"href": "http://localhost:3000/contacts"
}
],
"queries": [
{
"rel": "search",
"href": "http://localhost:3000/contacts/search",
"data": [
{
"name": "team_id",
"value": null
},
]
}
]
}
}
/contacts
{
"collection": {
"version": "3.454.0",
"href": "http://localhost:3000/contacts",
"rel": "contacts",
"template": {
...
},
"links": [
....
],
"queries": [
...
],
"items": [
{
"href": "http://localhost:3000/contacts/1",
"data": [
{
"name": "id",
"value": 1
},
{
"name": "type",
"value": "contact"
},
{
"name": "member_id",
"value": 63
},
{
"name": "created_at",
"value": "2017-05-10T17:28:05Z",
"type": "DateTime"
},
],
"links": [
{
"rel": "contact_email_addresses",
"href": "http://localhost:3000/contact_email_addresses/search?contact_id=1"
},
],
"rel": "contact-1"
}
]
}
}
/contacts/1
Thank you!
TeamSnap Tech Overview
By Dustin McCraw
TeamSnap Tech Overview
- 787