Skip to content
This repository was archived by the owner on Apr 25, 2024. It is now read-only.

Add RESTful end point to access continous aggregate group queries #143

Draft
wants to merge 31 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
f138af0
remove unused rails components
camallen Jun 24, 2021
8e70b09
add rubocop
camallen Jun 24, 2021
2a0c82d
align local ruby to docker version
camallen Jun 24, 2021
6a7c7d6
upgrade to latest 1.x timescale extension version
camallen Jun 24, 2021
1b6dc51
update dev gems for FS changes
camallen Jun 25, 2021
d621d5a
add group_id migration
camallen Jun 25, 2021
9f6d6fd
add rake db setup tasks
camallen Jun 25, 2021
f3bf241
add group_id generation for seed data
camallen Jun 25, 2021
eb2ce2f
simplify the docker context for builds
camallen Jun 25, 2021
174a74f
update group continuous aggregate sql
camallen Jun 25, 2021
993dc20
add dev env setup instructions for custom rake tasks
camallen Jun 25, 2021
23614c5
add test harness db setup
camallen Jun 25, 2021
c3555cc
remove unused gem
camallen Jun 25, 2021
dd3cd4a
document how to setup the test db
camallen Jun 25, 2021
e0d2cf8
remove unused version constant
camallen Jun 25, 2021
5c34936
rename the view to group_events_day
camallen Jun 25, 2021
364d492
add routes for group event day resource
camallen Jun 25, 2021
5c798aa
avoid staging db truncation
camallen Jun 25, 2021
bf32a36
correctly name request spec
camallen Jun 25, 2021
4fb22ae
rename the model to match the view
camallen Jun 25, 2021
c7b39b6
add note on speeding up tests using spring
camallen Jun 25, 2021
e111f08
install spring rspec
camallen Jun 25, 2021
819f7e4
re-order gemfile
camallen Jun 25, 2021
01f8d4d
add basic json schema for group event day count results
camallen Jun 25, 2021
608000d
remove VERSION constant
camallen Jun 25, 2021
2852000
remove focus on request specs
camallen Jun 25, 2021
ac2775d
do not disable spring for testing / dev envs
camallen Jun 25, 2021
1b718b7
add per group filtering for group day count
camallen Jun 25, 2021
4060969
add serializer to simplify the controller
camallen Jun 29, 2021
f42bb3c
update comments
camallen Jun 29, 2021
5743004
add API docs
camallen Jun 29, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
config/master.key
tmp/*
log/*
2 changes: 1 addition & 1 deletion .ruby-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.5
2.6
28 changes: 15 additions & 13 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,40 +1,42 @@
# frozen_string_literal: true

source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

gem 'rails', '~> 5.2.2'
gem 'pg', '>= 0.18', '< 2.0'
gem 'puma'
gem 'activerecord-import'
gem 'bootsnap', '>= 1.1.0', require: false
gem 'graphql', '~> 1.8'
gem 'composite_primary_keys', '~> 11.1'
gem 'rollbar'
gem 'panoptes-client', '~> 0.3.8'
gem 'activerecord-import'
gem 'geocoder'
gem 'graphql', '~> 1.8'
gem 'panoptes-client', '~> 0.3.8'
gem 'pg', '>= 0.18', '< 2.0'
gem 'puma'
gem 'rack-cors', require: 'rack/cors'
gem 'rails', '~> 5.2.2'
gem 'rollbar'

group :production, :staging do
gem 'newrelic_rpm'
end


group :development, :test do
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
gem 'pry-rails', '~> 0.3.9'
gem 'foreman'
gem 'pry-rails'
gem 'rubocop'
end

group :development do
gem 'listen', '>= 3.0.5', '< 3.2'
gem 'spring'
gem 'spring-watcher-listen', '~> 2.0.0'
gem 'spring-watcher-listen'
end

group :test do
gem 'database_cleaner', '~> 1.6', '>= 1.6.2'
gem 'factory_bot_rails', '~> 4.8', '>= 4.8.2'
gem 'faker', '~> 1.8', '>= 1.8.7'
gem 'rspec-rails', '~> 3.8'
gem 'rspec-graphql_matchers'
gem 'shoulda-matchers', '~> 4.3'
gem 'rspec-rails'
gem 'shoulda-matchers'
gem 'spring-commands-rspec'
end
97 changes: 59 additions & 38 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,18 @@ GEM
minitest (~> 5.1)
tzinfo (~> 1.1)
arel (9.0.0)
ast (2.4.2)
bootsnap (1.3.2)
msgpack (~> 1.0)
builder (3.2.4)
byebug (10.0.2)
coderay (1.1.2)
composite_primary_keys (11.1.0)
activerecord (~> 5.2.1)
concurrent-ruby (1.1.7)
concurrent-ruby (1.1.9)
crass (1.0.6)
database_cleaner (1.7.0)
diff-lcs (1.3)
erubi (1.9.0)
diff-lcs (1.4.4)
erubi (1.10.0)
factory_bot (4.11.1)
activesupport (>= 3.0.0)
factory_bot_rails (4.11.1)
Expand All @@ -71,21 +71,21 @@ GEM
faraday_middleware (~> 0.10)
faraday_middleware (0.12.2)
faraday (>= 0.7.4, < 1.0)
ffi (1.9.25)
ffi (1.15.3)
foreman (0.85.0)
thor (~> 0.19.1)
geocoder (1.6.3)
globalid (0.4.2)
activesupport (>= 4.2.0)
graphql (1.8.13)
i18n (1.8.5)
i18n (1.8.10)
concurrent-ruby (~> 1.0)
jwt (1.5.6)
listen (3.1.5)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
ruby_dep (~> 1.2)
loofah (2.7.0)
loofah (2.10.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
mail (2.7.1)
Expand All @@ -97,20 +97,23 @@ GEM
nokogiri (~> 1)
rake
mini_mime (1.0.2)
mini_portile2 (2.5.1)
minitest (5.14.2)
mini_portile2 (2.5.3)
minitest (5.14.4)
msgpack (1.2.4)
multi_json (1.13.1)
multipart-post (2.0.0)
newrelic_rpm (6.10.0.364)
nio4r (2.5.7)
nokogiri (1.11.4)
nokogiri (1.11.7)
mini_portile2 (~> 2.5.0)
racc (~> 1.4)
panoptes-client (0.3.8)
faraday
faraday-panoptes (~> 0.3.0)
jwt (~> 1.5.0)
parallel (1.20.1)
parser (3.0.1.1)
ast (~> 2.4.1)
pg (1.1.4)
pry (0.12.2)
coderay (~> 1.1.0)
Expand Down Expand Up @@ -149,36 +152,52 @@ GEM
method_source
rake (>= 0.8.7)
thor (>= 0.19.0, < 2.0)
rake (13.0.1)
rb-fsevent (0.10.3)
rb-inotify (0.9.10)
ffi (>= 0.5.0, < 2)
rainbow (3.0.0)
rake (13.0.3)
rb-fsevent (0.11.0)
rb-inotify (0.10.1)
ffi (~> 1.0)
regexp_parser (2.1.1)
rexml (3.2.5)
rollbar (2.18.2)
multi_json
rspec-core (3.8.0)
rspec-support (~> 3.8.0)
rspec-expectations (3.8.2)
rspec-core (3.10.1)
rspec-support (~> 3.10.0)
rspec-expectations (3.10.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.8.0)
rspec-support (~> 3.10.0)
rspec-graphql_matchers (0.7.1)
graphql (>= 0.9, < 2)
rspec-mocks (3.8.0)
rspec-mocks (3.10.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.8.0)
rspec-rails (3.8.1)
actionpack (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
rspec-core (~> 3.8.0)
rspec-expectations (~> 3.8.0)
rspec-mocks (~> 3.8.0)
rspec-support (~> 3.8.0)
rspec-support (3.8.0)
rspec-support (~> 3.10.0)
rspec-rails (5.0.1)
actionpack (>= 5.2)
activesupport (>= 5.2)
railties (>= 5.2)
rspec-core (~> 3.10)
rspec-expectations (~> 3.10)
rspec-mocks (~> 3.10)
rspec-support (~> 3.10)
rspec-support (3.10.2)
rubocop (1.17.0)
parallel (~> 1.10)
parser (>= 3.0.0.0)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml
rubocop-ast (>= 1.7.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 3.0)
rubocop-ast (1.7.0)
parser (>= 3.0.1.1)
ruby-progressbar (1.11.0)
ruby_dep (1.5.0)
shoulda-matchers (4.3.0)
shoulda-matchers (4.5.1)
activesupport (>= 4.2.0)
spring (2.0.2)
activesupport (>= 4.2)
spring (2.1.1)
spring-commands-rspec (1.0.4)
spring (>= 0.9.1)
spring-watcher-listen (2.0.1)
listen (>= 2.7, < 4.0)
spring (>= 1.2, < 3.0)
Expand All @@ -191,8 +210,9 @@ GEM
sprockets (>= 3.0.0)
thor (0.19.4)
thread_safe (0.3.6)
tzinfo (1.2.7)
tzinfo (1.2.9)
thread_safe (~> 0.1)
unicode-display_width (2.0.0)
websocket-driver (0.7.3)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
Expand All @@ -203,7 +223,6 @@ PLATFORMS
DEPENDENCIES
activerecord-import
bootsnap (>= 1.1.0)
byebug
composite_primary_keys (~> 11.1)
database_cleaner (~> 1.6, >= 1.6.2)
factory_bot_rails (~> 4.8, >= 4.8.2)
Expand All @@ -215,16 +234,18 @@ DEPENDENCIES
newrelic_rpm
panoptes-client (~> 0.3.8)
pg (>= 0.18, < 2.0)
pry-rails (~> 0.3.9)
pry-rails
puma
rack-cors
rails (~> 5.2.2)
rollbar
rspec-graphql_matchers
rspec-rails (~> 3.8)
shoulda-matchers (~> 4.3)
rspec-rails
rubocop
shoulda-matchers
spring
spring-watcher-listen (~> 2.0.0)
spring-commands-rspec
spring-watcher-listen

BUNDLED WITH
1.17.3
55 changes: 17 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,10 @@
[![Build Status](https://travis-ci.org/zooniverse/zoo-stats-api-graphql.svg?branch=master)](https://travis-ci.org/zooniverse/zoo-stats-api-graphql)

#### API
The stats service has a GraphQL API, https://graphql.org/ which differs to RESTful APIs.

There is only one endpoint path for this API `/graphql` and it only supports the `POST` HTTP method for the `application/json` content type.
The stats service has a GraphQL API, https://graphql.org/ and a RESTful API.

###### POST /graphql (application/json)

**Introspect the available operations**

```
curl -d '{"query": "{__schema {queryType {name fields {name}}mutationType {name fields {name}}}}"}' -H "Content-Type: application/json" -X POST https://graphql-stats.zooniverse.org/graphql
```

**Event type counts per interval**
Retrieve the number of classifications for a specified event type for a known interval. Non-required attributes are `projectID` and `userId` to filter the results.

Note: If you supply the the userId attribute you **must** provide a bearer token in the Authorization header, e.g.
`Authorization: Bearer <TOKEN>`

You must supply and `eventType`, `interval` and `window`. Valid intervals are postgres intervals, e.g. `2 Days`, `24 Hours`, `60 Seconds`
Valid windows are postgres intervals, e.g. `7 Days`, `2 Weeks`, `1 Month`, `1 Year`.

```
{
statsCount(
eventType: "classification",
interval: "1 Day",
window: "1 week",
projectId: "${project.id}",
userId: "${user.id}"
){
period,
count
}
}
```

Note: `classification` events are currently the only supported event types.
See [the API docs](./docs/API.md) for more details

#### Getting Started

Expand All @@ -52,7 +19,19 @@ Note: `classification` events are currently the only supported event types.

0. Create and run the application containers with `docker-compose up`

0. If the above step reports a missing database error, kill the docker-compose process or open a new terminal window in the current directory and then run `docker-compose run --rm zoo_stats bundle exec rake db:setup` to setup the database. This command will launch a new Docker container, run the rake DB setup task, and then clean up the container.
0. If the above step reports a missing database error, kill the docker-compose process or open a new terminal window in the current directory and then to setup the database run

Setup the development database without any data

``` sh
docker-compose run --rm zoo_stats bundle exec rake db:setup:development
```

Setup the development database with example data

``` sh
docker-compose run --rm zoo_stats bundle exec rake db:setup:seed:development
```

0. Open up the application in your browser at http://localhost:3000

Expand All @@ -64,14 +43,14 @@ Note: You will need to re-install the gem dependencies for the application if yo
#### Testing

1. Setup the test environment and database
* Run: `docker-compose run --rm -e RAILS_ENV=test zoo_stats bundle exec rake db:setup`
* Run: `docker-compose run --rm -e RAILS_ENV=test zoo_stats bundle exec rake db:create`

0. Run the tests
* Run: `docker-compose run -T --rm -e RAILS_ENV=test zoo_stats bundle exec rspec`

0. Get a console to interactively run / debug tests
* Run: `docker-compose run --rm -e RAILS_ENV=test zoo_stats bash`
* Then in the container run: `bundle exec rspec`
* Then in the container run: `bin/rspec` to run the test suite using Spring code loader (speeds up iterative testing)

### Setup Docker and Docker Compose

Expand Down
3 changes: 1 addition & 2 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ class ApplicationController < ActionController::API

def health
render json: {
status: "ok",
version: VERSION,
status: 'ok',
database_status: db_connection_status,
commit_id: ENV['REVISION']
}.to_json
Expand Down
19 changes: 19 additions & 0 deletions app/controllers/group_events_day_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

class GroupEventsDayController < ApplicationController
def index
events_scope = GroupEventsDay.all
render json: EventsSerializer.new(events_scope), serializer_options: serializer_opts_from_params
end

def show
events_scope = GroupEventsDay.where(group_id: params[:id])
render json: EventsSerializer.new(events_scope), serializer_options: serializer_opts_from_params
end

private

def serializer_opts_from_params
{ limit: params[:limit], order: params[:order] }
end
end
20 changes: 20 additions & 0 deletions app/models/group_events_day.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

# AR model over the 'group_events_day' continuous aggregate view
# to ease the sql query formation
class GroupEventsDay < ApplicationRecord
self.table_name = 'group_events_day'
# save rails from failing if save is called (not strictly necessary)
def readonly?
true
end

# example queries
#
# SQL
# SELECT * FROM group_events_day order by period ASC LIMIT 1;
#
# ActiveRecord
# GroupEventsDay.where(group_id: 124).order(period: :asc)
# GroupEventsDay.where(group_id: 124).where("period >= ?", "2021-06-18").order(period: :asc)
end
Loading