The purpose of this service is to make the life of administrators of football sites easier.
Instead of monitoring football matches and adding results manually, their apps can use the webhook to receive results automatically.
result-service is created for prognoz project (web-app, api), but not restricted to only it.
Feel free to use this service for your needs.
(Integration with prognoz project as an example)
- Football Result Service /
result-service- This service. - External Results API (Fotmob) /
fotmob-api- The source of the football matches results. - Prognoz API Server /
prognoz-api- The service that wants to receive the results. - Google Cloud Tasks /
cloud-tasks- The service that schedules tasks to check match results and notify subscribers.
result-service has a relational database. It is visually represented below:
erDiagram
Team {
Int id PK
}
Alias {
Int id PK
Int team_id FK
String alias UK
}
Match {
Int id PK
Int home_team_id FK
Int away_team_id FK
Date starts_at
String result_status
}
ExternalMatch {
Int id PK
Int match_id FK
Int home_score
Int away_score
String status
}
Subscription {
Int id PK
String url UK
Int match_id FK
String key
String status
String subscriber_error
Date notified_at
Date created_at
}
ExternalTeam {
Int id PK
Int team_id FK
}
CheckResultTask {
Int id PK
Int match_id FK
String name UK
Int attempt_number
Date execute_at
Date created_at
}
Team ||--o{ Alias : has
Team ||--o{ Match : has
Match ||--|| ExternalMatch : has
Match ||--o{ Subscription : has
Team ||--|| ExternalTeam : has
Match ||--|| CheckResultTask : has
Table names are pluralized. The tables teams, aliases, external-teams are pre-filled with the data of fotmob-api.
result_status |
Description |
|---|---|
not_scheduled |
Match is created, but fixture creation or task scheduling fails |
scheduled |
Match is created and a task is scheduled. If there was an attempt to get a result but a match was not ended the status scheduled remains unchanged. |
scheduling_error |
An attempt to reschedule task was unsuccessful. |
received |
Match result is received. |
api_error |
Request to fotmob-api to get match result was unsuccessful. |
cancelled |
Received a status from fotmob-api indicates that match was canceled. No new task is rescheduled. |
subscription_status |
Description |
|---|---|
pending |
Subscription is created, but match result is not yet received. |
scheduling_error |
Attempt to create a task was unsuccessful. |
successful |
Subscriber successfully notified. Column notified_at gets a value. |
subscriber_error |
Subscriber returned an error. Column error gets a value. |
flowchart TD
subgraph Group 1
A[Create a match] --> B[Subscribe on result receiving]
end
subgraph Group 2
C[Receive trigger to check match result] --> D[Notify subscribers]
end
E[Delete a subscription]
B --> C
B --> E
sequenceDiagram
participant API as prognoz-api
participant ResultService as result-service
participant Fotmob as fotmob-api
participant CloudTasks as cloud-tasks
API->>ResultService: Sends a request to create a match
Activate ResultService
ResultService->>ResultService: Gets team ids by aliases from the DB
ResultService->>ResultService: Gets match by team ids and starting time from the DB
alt match is found and result status is scheduled
ResultService-->>API: Returns match response
end
ResultService->>+Fotmob: Sends a request with date
Fotmob-->>-ResultService: Returns all matches for the date
ResultService->>ResultService: Finds a match in the response by aliases and starting time
ResultService->>ResultService: Saves match with status not_scheduled and external match to the DB
ResultService->>CloudTasks: Creates a task to check result with schedule-time (starting time + 115 minutes)
Activate CloudTasks
CloudTasks-->>ResultService: Returns task id
Deactivate CloudTasks
ResultService->>ResultService: Saves check result task to the DB
ResultService->>ResultService: Updates match status to scheduled
ResultService-->>API: Returns match response
Deactivate ResultService
sequenceDiagram
participant API as prognoz-api
participant ResultService as result-service
API->>ResultService: Sends a request to create subscription
Activate ResultService
ResultService->>ResultService: Gets match from the DB
alt Match result status in not scheduled
ResultService-->>API: Returns error
end
ResultService->>ResultService: Saves subscription to the DB
ResultService-->>API: Returns success
Deactivate ResultService
sequenceDiagram
participant CloudTasks as cloud-tasks
participant ResultService as result-service
participant Fotmob as fotmob-api
CloudTasks->>+ResultService: Sends a request to check match result
ResultService->>+Fotmob: Sends a request with date
Fotmob-->>-ResultService: Returns all matches for the date
ResultService->>ResultService: Finds a match in the response by id
ResultService->>ResultService: Updates external match data
alt match is not yet ended
ResultService->>CloudTasks: Creates a new task to check result with backoff
ResultService-->>CloudTasks: Returns success
end
ResultService->>ResultService: Gets all subscriptions of the match from the DB
loop Each subscription
ResultService->>CloudTasks: Create a task to notify subscriber
end
ResultService-->>-CloudTasks: Returns success
sequenceDiagram
participant CloudTasks as cloud-tasks
participant ResultService as result-service
participant API as prognoz-api
CloudTasks->>+ResultService: Sends a request to notify subscriber
ResultService->>ResultService: Gets a subscription and a match from the DB
ResultService->>+API: Sends a request with the match result
API-->>-ResultService: Returns success
ResultService->>ResultService: Updates subscription status
ResultService-->>-CloudTasks: Returns success
sequenceDiagram
participant API as prognoz-api
participant ResultService as result-service
participant CloudTasks as cloud-tasks
API->>ResultService: Sends a request to remove subscription
Activate ResultService
ResultService->>ResultService: Deletes subscription from DB
alt other subscriptions for this match exist
ResultService-->>API: Returns success
end
ResultService->>CloudTasks: Sends a request to remove scheduled task
Activate CloudTasks
CloudTasks-->>ResultService: Returns success
Deactivate CloudTasks
ResultService->>ResultService: Removes match and fixture from DB
ResultService-->>API: Returns success
Deactivate ResultService
prognoz-api => result-service
- A secret key is generated, hashed and set to env variables
prognoz-apiattaches secret key to requests toresult-serviceresult-servicehas a middleware that checks presence and validity of secret-key
result-service => prognoz-api
- When
prognoz-apicreates a subscription it sends a secret-key - Secret-key is saved in
subscriptionstable for each subscription - When
result-servicecalls subscriptionurlit attaches secret-key to the request
To back-fill aliases data a separate command is created. The command description:
- Accepts dates as a parameter
- Command has predefined list of league and country names (for example: Premier League - Ukraine, La Liga - Spain, etc.)
- For each date param calls
fotmob-apismatchesendpoint - Extracts team names from the matches list
- For each team the command does the next actions in database
- checks if
aliasalready exists - if not, creates a
team,alias,external_teamin transaction
- checks if
Run a particular functional test:
go test -v -count=1 -tags functional ./functionaltests/... -testify.m TestCreateMatch_ExternalAPIReturnsError