timescaledb 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 91dfb6aac43ec8ab347ac9cf1bc553631310259cd4f6726c42f466c08f74c761
4
- data.tar.gz: 4436ff5f2067264fc814592efebaa9ce32d69ece7607e7d728a95356db04f739
3
+ metadata.gz: c64be262fa0fbecf13ec6b6b8820b471c9d83e6842306efc59b950a693d4755b
4
+ data.tar.gz: d702011692906410bd38107d16f9f20801977deb8f4a0cc3372dc5f61aed29ae
5
5
  SHA512:
6
- metadata.gz: 71492adbe4cd1771db48b2b796affa50d3f3157b420f59482e61d4a76dfc8fcec52f5face66047fc8069f5bcdd35bace4c8ff4e0fec88ffe1331872b3d625862
7
- data.tar.gz: 4ecf26d66361af9d79cf33f99b9a25b8233df229a0ffa6ac33afe54d4f4c4d03e6c13609c60cceabc95dc30d8e49f7343588174fb0715bda044942360ebed53b
6
+ metadata.gz: bc45bab9ddc1e32c1630bb4258299ee1a74b5b7991eb9281332d7de77161e4ad76cedb0cc2ddb30dbf609b68607a2cf0d7799c11130348bda94974fd46d152c1
7
+ data.tar.gz: 4b6e7da46622c902fc1960fcba1b4d41b4674a8490eef2025f835b767efd3838573befffaed7fffceb65de5e65c793453d3eacfc681a1846f13ba2b485897ce6
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- timescaledb (0.1.2)
4
+ timescaledb (0.1.4)
5
5
  activerecord
6
6
  pg (~> 1.2)
7
7
 
@@ -21,6 +21,10 @@ GEM
21
21
  zeitwerk (~> 2.3)
22
22
  coderay (1.1.3)
23
23
  concurrent-ruby (1.1.9)
24
+ database_cleaner-active_record (2.0.1)
25
+ activerecord (>= 5.a)
26
+ database_cleaner-core (~> 2.0.0)
27
+ database_cleaner-core (2.0.1)
24
28
  diff-lcs (1.4.4)
25
29
  dotenv (2.7.6)
26
30
  i18n (1.8.10)
@@ -56,6 +60,7 @@ PLATFORMS
56
60
  ruby
57
61
 
58
62
  DEPENDENCIES
63
+ database_cleaner-active_record
59
64
  dotenv
60
65
  pry
61
66
  rake (~> 12.0)
data/README.md CHANGED
@@ -290,132 +290,107 @@ options = {
290
290
  create_continuous_aggregates('ohlc_1m', query, **options)
291
291
  ```
292
292
 
293
- ### Hypertable Helpers
293
+ ### Enable ActsAsHypertable
294
294
 
295
- You can say `acts_as_hypertable` to get access to some basic scopes for your
295
+ You can declare a Rails model as a Hypertable by invoking the `acts_as_hypertable` macro. This macro extends your existing model with timescaledb-related functionality.
296
296
  model:
297
297
 
298
298
  ```ruby
299
299
  class Event < ActiveRecord::Base
300
- self.primary_key = "identifier"
301
-
302
300
  acts_as_hypertable
303
301
  end
304
302
  ```
305
303
 
306
- After including the helpers, several methods from timescaledb will be available in the
307
- model.
304
+ By default, ActsAsHypertable assumes a record's _time_column_ is called `created_at`.
308
305
 
309
- ### Chunks
306
+ ### Options
310
307
 
311
- To get chunks from a single hypertable, you can use the `.chunks` directly from
312
- the model name.
308
+ If you are using a different time_column name, you can specify it as follows when invoking the `acts_as_hypertable` macro:
313
309
 
314
310
  ```ruby
315
- Event.chunks
316
- # DEBUG: Timescale::Chunk Load (9.0ms) SELECT "timescaledb_information"."chunks".* FROM "timescaledb_information"."chunks" WHERE "timescaledb_information"."chunks"."hypertable_name" = $1 [["hypertable_name", "events"]]
317
- # => [#<Timescale::Chunk:0x00007f94b0c86008
318
- # hypertable_schema: "public",
319
- # hypertable_name: "events",
320
- # chunk_schema: "_timescaledb_internal",
321
- # chunk_name: "_hyper_180_74_chunk",
322
- # primary_dimension: "created_at",
323
- # primary_dimension_type: "timestamp without time zone",
324
- # range_start: 2021-09-22 21:28:00 +0000,
325
- # range_end: 2021-09-22 21:29:00 +0000,
326
- # range_start_integer: nil,
327
- # range_end_integer: nil,
328
- # is_compressed: false,
329
- # chunk_tablespace: nil,
330
- # data_nodes: nil>
311
+ class Event < ActiveRecord::Base
312
+ acts_as_hypertable time_column: :timestamp
313
+ end
331
314
  ```
332
315
 
333
- To get all hypertables you can use `Timescale.hypertables` method.
316
+ ### Chunks
317
+
318
+ To get all the chunks from a model's hypertable, you can use `.chunks`.
334
319
 
335
- ### Hypertable metadata from model
320
+ ```ruby
321
+ Event.chunks # => [#<Timescale::Chunk>, ...]
322
+ ```
336
323
 
337
- To get all details from hypertable, you can access the `.hypertable` from the
338
- model.
324
+ ### Hypertable metadata
325
+
326
+ To get the models' hypertable metadata, you can use `.hypertable`.
339
327
 
340
328
  ```ruby
341
- Event.hypertable
342
- # Timescale::Hypertable Load (4.8ms) SELECT "timescaledb_information"."hypertables".* FROM "timescaledb_information"."hypertables" WHERE "timescaledb_information"."hypertables"."hypertable_name" = $1 LIMIT $2 [["hypertable_name", "events"], ["LIMIT", 1]]
343
- # => #<Timescale::Hypertable:0x00007f94c3151cd8
344
- # hypertable_schema: "public",
345
- # hypertable_name: "events",
346
- # owner: "jonatasdp",
347
- # num_dimensions: 1,
348
- # num_chunks: 1,
349
- # compression_enabled: true,
350
- # is_distributed: false,
351
- # replication_factor: nil,
352
- # data_nodes: nil,
353
- # tablespaces: nil>
329
+ Event.hypertable # => #<Timescale::Hypertable>
354
330
  ```
355
331
 
356
- You can also use `Timescale.hypertables` to have access of all hypertables
357
- metadata.
332
+ To get hypertable metadata for all hypertables: `Timescale.hypertables`.
358
333
 
359
334
  ### Compression Settings
360
335
 
361
336
  Compression settings are accessible through the hypertable.
362
337
 
363
338
  ```ruby
364
- Event.hypertable.compression_settings
365
- # Timescale::Hypertable Load (1.2ms) SELECT "timescaledb_information"."hypertables".* FROM "timescaledb_information"."hypertables" WHERE "timescaledb_information"."hypertables"."hypertable_name" = $1 LIMIT $2 [["hypertable_name", "events"], ["LIMIT", 1]]
366
- # Timescale::CompressionSettings Load (1.2ms) SELECT "timescaledb_information"."compression_settings".* FROM "timescaledb_information"."compression_settings" WHERE "timescaledb_information"."compression_settings"."hypertable_name" = $1 [["hypertable_name", "events"]]
367
- # => [#<Timescale::CompressionSettings:0x00007f94b0bf7010
368
- # hypertable_schema: "public",
369
- # hypertable_name: "events",
370
- # attname: "identifier",
371
- # segmentby_column_index: 1,
372
- # orderby_column_index: nil,
373
- # orderby_asc: nil,
374
- # orderby_nullsfirst: nil>,
375
- # #<Timescale::CompressionSettings:0x00007f94b0c3e460
376
- # hypertable_schema: "public",
377
- # hypertable_name: "events",
378
- # attname: "created_at",
379
- # segmentby_column_index: nil,
380
- # orderby_column_index: 1,
381
- # orderby_asc: true,
382
- # orderby_nullsfirst: false>]
339
+ Event.hypertable.compression_settings # => [#<Timescale::CompressionSettings>, ...]
383
340
  ```
384
341
 
385
- It's also possible to access all data calling `Timescale.compression_settings`.
342
+ To get compression settings for all hypertables: `Timescale.compression_settings`.
386
343
 
387
- ### RSpec Hooks
344
+ ### Scopes
388
345
 
389
- In case you want to use TimescaleDB on a Rails environment, you may have some
390
- issues as the schema dump used for tests is not considering hypertables
391
- metadata.
346
+ When you enable ActsAsHypertable on your model, we include a couple default scopes. They are:
392
347
 
393
- If you add the `acts_as_hypertable` to your model, you can dynamically
394
- verify if the `Timescale::ActsAsHypertable` module is included to
395
- create the hypertable for testing environment.
348
+ | Scope name | What they return |
349
+ |------------------------|---------------------------------------|
350
+ | `Model.previous_month` | Records created in the previous month |
351
+ | `Model.previous_week` | Records created in the previous week |
352
+ | `Model.this_month` | Records created this month |
353
+ | `Model.this_week` | Records created this week |
354
+ | `Model.yesterday` | Records created yesterday |
355
+ | `Model.today` | Records created today |
356
+ | `Model.last_hour` | Records created in the last hour |
396
357
 
397
- Consider adding this hook to your `spec/rspec_helper.rb` file:
358
+ All time-related scopes respect your application's timezone.
359
+
360
+ ## RSpec Hooks
361
+
362
+ In case you want to use TimescaleDB on a Rails environment, you may have some
363
+ issues as the schema dump used for tests does not consider hypertables metadata.
364
+
365
+ As a work around, you can dynamically create the hypertables yourself for
366
+ testing environments using the following hook which you can
367
+ define in `spec/rspec_helper.rb`:
398
368
 
399
369
  ```ruby
400
- config.before(:suite) do
401
- hypertable_models = ApplicationRecord
402
- .descendants
403
- .select{|clazz| clazz.included_modules.include?(Timescale::ActsAsHypertable)
404
- hypertable_models.each do |clazz|
405
- if clazz.hypertable.exists?
406
- ApplicationRecord.logger.info "skip recreating hypertable for '#{clazz.table_name}'."
407
- next
408
- end
409
- ApplicationRecord.connection.execute <<~SQL
410
- SELECT create_hypertable('#{clazz.table_name}', 'created_at')
411
- SQL
370
+ config.before(:suite) do
371
+ hypertable_models = ActiveRecord::Base.descendants.select(&:acts_as_hypertable?)
372
+
373
+ hypertable_models.each do |klass|
374
+ table_name = klass.table_name
375
+ time_column = klass.hypertable_options[:time_column]
376
+
377
+ if klass.try(:hypertable).present?
378
+ ApplicationRecord.logger.info "hypertable already created for '#{table_name}', skipping."
379
+ next
412
380
  end
381
+
382
+ ApplicationRecord.connection.execute <<~SQL
383
+ SELECT create_hypertable('#{table_name}', '#{time_column.to_s}')
384
+ SQL
413
385
  end
386
+ end
414
387
  ```
415
388
 
416
389
  ## Development
417
390
 
418
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `tsdb` for an interactive prompt that will allow you to experiment.
391
+ After checking out the repo, run `bin/setup` to install the development dependencies. Then, `bundle exec rake test:setup` to setup the test database and tables. Finally, run `bundle exec rspec` to run the tests.
392
+
393
+ You can also run `tsdb` for an interactive prompt that will allow you to experiment.
419
394
 
420
395
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
421
396
 
data/Rakefile CHANGED
@@ -3,4 +3,13 @@ require "rspec/core/rake_task"
3
3
 
4
4
  RSpec::Core::RakeTask.new(:spec)
5
5
 
6
- task :default => :spec
6
+ task default: :spec
7
+
8
+ namespace :test do
9
+ task :setup do
10
+ require_relative "spec/spec_helper"
11
+
12
+ teardown_tables
13
+ setup_tables
14
+ end
15
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Timescale
4
+ module ActsAsHypertable
5
+ module Core
6
+ def self.included(base)
7
+ base.extend(ClassMethods)
8
+ end
9
+
10
+ module ClassMethods
11
+ def time_column
12
+ @time_column ||= hypertable_options[:time_column] || :created_at
13
+ end
14
+
15
+ protected
16
+
17
+ def define_association_scopes
18
+ scope :chunks, -> do
19
+ Chunk.where(hypertable_name: table_name)
20
+ end
21
+
22
+ scope :hypertable, -> do
23
+ Hypertable.find_by(hypertable_name: table_name)
24
+ end
25
+
26
+ scope :jobs, -> do
27
+ Job.where(hypertable_name: table_name)
28
+ end
29
+
30
+ scope :job_stats, -> do
31
+ JobStats.where(hypertable_name: table_name)
32
+ end
33
+
34
+ scope :compression_settings, -> do
35
+ CompressionSettings.where(hypertable_name: table_name)
36
+ end
37
+
38
+ scope :continuous_aggregates, -> do
39
+ ContinuousAggregates.where(hypertable_name: table_name)
40
+ end
41
+ end
42
+
43
+ def define_default_scopes
44
+ scope :previous_month, -> do
45
+ where(
46
+ "DATE(#{time_column}) >= :start_time AND DATE(#{time_column}) <= :end_time",
47
+ start_time: Date.today.last_month.in_time_zone.beginning_of_month.to_date,
48
+ end_time: Date.today.last_month.in_time_zone.end_of_month.to_date
49
+ )
50
+ end
51
+
52
+ scope :previous_week, -> do
53
+ where(
54
+ "DATE(#{time_column}) >= :start_time AND DATE(#{time_column}) <= :end_time",
55
+ start_time: Date.today.last_week.in_time_zone.beginning_of_week.to_date,
56
+ end_time: Date.today.last_week.in_time_zone.end_of_week.to_date
57
+ )
58
+ end
59
+
60
+ scope :this_month, -> do
61
+ where(
62
+ "DATE(#{time_column}) >= :start_time AND DATE(#{time_column}) <= :end_time",
63
+ start_time: Date.today.in_time_zone.beginning_of_month.to_date,
64
+ end_time: Date.today.in_time_zone.end_of_month.to_date
65
+ )
66
+ end
67
+
68
+ scope :this_week, -> do
69
+ where(
70
+ "DATE(#{time_column}) >= :start_time AND DATE(#{time_column}) <= :end_time",
71
+ start_time: Date.today.in_time_zone.beginning_of_week.to_date,
72
+ end_time: Date.today.in_time_zone.end_of_week.to_date
73
+ )
74
+ end
75
+
76
+ scope :yesterday, -> { where("DATE(#{time_column}) = ?", Date.yesterday.in_time_zone.to_date) }
77
+ scope :today, -> { where("DATE(#{time_column}) = ?", Date.today.in_time_zone.to_date) }
78
+ scope :last_hour, -> { where("#{time_column} > ?", 1.hour.ago.in_time_zone) }
79
+ end
80
+
81
+ def normalize_hypertable_options
82
+ hypertable_options[:time_column] = hypertable_options[:time_column].to_sym
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
@@ -18,97 +18,45 @@ module Timescale
18
18
  # acts_as_hypertable
19
19
  # end
20
20
  #
21
- # @see Timescale::ActsAsHypertable::ClassMethods#acts_as_hypertable
21
+ # @see Timescale::ActsAsHypertable#acts_as_hypertable
22
22
  # for configuration options
23
23
  module ActsAsHypertable
24
- extend ActiveSupport::Concern
25
-
26
24
  DEFAULT_OPTIONS = {
27
25
  time_column: :created_at
28
26
  }.freeze
29
27
 
30
- module ClassMethods
31
- # == Configuration options
32
- #
33
- # @param [Hash] options The options to initialize your macro with.
34
- # @option options [Symbol] :time_column The name of the column in your
35
- # model's table containing time values. The name provided should be
36
- # the same name as the `time_column_name` you passed to the
37
- # TimescaleDB `create_hypertable` function.
38
- #
39
- # @example Enabling the macro on your model with options
40
- # class Event < ActiveRecord::Base
41
- # acts_as_hypertable time_column: :timestamp
42
- # end
43
- #
44
- def acts_as_hypertable(options = {})
45
- return if already_declared_as_hypertable?
46
-
47
- extend Timescale::ActsAsHypertable::HypertableClassMethods
48
-
49
- class_attribute :hypertable_options, instance_writer: false
50
-
51
- self.hypertable_options = DEFAULT_OPTIONS.dup
52
- hypertable_options.merge!(options)
53
- normalize_hypertable_options
54
-
55
- define_association_scopes
56
- define_default_scopes
57
- end
58
-
59
- def define_association_scopes
60
- scope :chunks, -> do
61
- Chunk.where(hypertable_name: table_name)
62
- end
63
-
64
- scope :hypertable, -> do
65
- Hypertable.find_by(hypertable_name: table_name)
66
- end
67
-
68
- scope :jobs, -> do
69
- Job.where(hypertable_name: table_name)
70
- end
71
-
72
- scope :job_stats, -> do
73
- JobStats.where(hypertable_name: table_name)
74
- end
75
-
76
- scope :compression_settings, -> do
77
- CompressionSettings.where(hypertable_name: table_name)
78
- end
79
-
80
- scope :continuous_aggregates, -> do
81
- ContinuousAggregates.where(hypertable_name: table_name)
82
- end
83
- end
84
-
85
- def define_default_scopes
86
- scope :last_month, -> { where("#{time_column} > ?", 1.month.ago) }
87
- scope :last_week, -> { where("#{time_column} > ?", 1.week.ago) }
88
- scope :last_hour, -> { where("#{time_column} > ?", 1.hour.ago) }
89
- scope :yesterday, -> { where("#{time_column} = ?", 1.day.ago.to_date) }
90
- scope :today, -> { where("#{time_column} = ?", Date.today) }
91
- end
92
-
93
- private
94
-
95
- def already_declared_as_hypertable?
96
- singleton_class
97
- .included_modules
98
- .include?(Timescale::ActsAsHypertable::HypertableClassMethods)
99
- end
28
+ def acts_as_hypertable?
29
+ included_modules.include?(Timescale::ActsAsHypertable::Core)
100
30
  end
101
31
 
102
- module HypertableClassMethods
103
- def time_column
104
- @hypertable_time_column ||= hypertable_options[:time_column] || :created_at
105
- end
106
-
107
- protected
108
-
109
- def normalize_hypertable_options
110
- hypertable_options[:time_column] = hypertable_options[:time_column].to_sym
111
- end
32
+ # == Configuration options
33
+ #
34
+ # @param [Hash] options The options to initialize your macro with.
35
+ # @option options [Symbol] :time_column The name of the column in your
36
+ # model's table containing time values. The name provided should be
37
+ # the same name as the `time_column_name` you passed to the
38
+ # TimescaleDB `create_hypertable` function.
39
+ #
40
+ # @example Enabling the macro on your model with options
41
+ # class Event < ActiveRecord::Base
42
+ # acts_as_hypertable time_column: :timestamp
43
+ # end
44
+ #
45
+ def acts_as_hypertable(options = {})
46
+ return if acts_as_hypertable?
47
+
48
+ include Timescale::ActsAsHypertable::Core
49
+
50
+ class_attribute :hypertable_options, instance_writer: false
51
+
52
+ self.hypertable_options = DEFAULT_OPTIONS.dup
53
+ hypertable_options.merge!(options)
54
+ normalize_hypertable_options
55
+
56
+ define_association_scopes
57
+ define_default_scopes
112
58
  end
113
59
  end
114
60
  end
61
+
62
+ ActiveRecord::Base.extend Timescale::ActsAsHypertable
@@ -1,3 +1,3 @@
1
1
  module Timescale
2
- VERSION = '0.1.3'
2
+ VERSION = '0.1.4'
3
3
  end
data/lib/timescale.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'active_record'
2
2
 
3
3
  require_relative 'timescale/acts_as_hypertable'
4
+ require_relative 'timescale/acts_as_hypertable/core'
4
5
  require_relative 'timescale/chunk'
5
6
  require_relative 'timescale/compression_settings'
6
7
  require_relative 'timescale/continuous_aggregates'
@@ -47,7 +48,3 @@ module Timescale
47
48
  Timescale::ActsAsHypertable::DEFAULT_OPTIONS
48
49
  end
49
50
  end
50
-
51
- ActiveSupport.on_load :active_record do
52
- include Timescale::ActsAsHypertable
53
- end
data/timescale.gemspec CHANGED
@@ -35,4 +35,5 @@ Gem::Specification.new do |spec|
35
35
  spec.add_development_dependency "rspec", "~> 3.0"
36
36
  spec.add_development_dependency "dotenv"
37
37
  spec.add_development_dependency "rake", "~> 12.0"
38
+ spec.add_development_dependency "database_cleaner-active_record"
38
39
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timescaledb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jônatas Davi Paganini
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-10-07 00:00:00.000000000 Z
11
+ date: 2021-10-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pg
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
110
  version: '12.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: database_cleaner-active_record
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
111
125
  description: Functions from timescaledb available in the ActiveRecord models.
112
126
  email:
113
127
  - jonatasdp@gmail.com
@@ -133,6 +147,7 @@ files:
133
147
  - examples/all_in_one.rb
134
148
  - lib/timescale.rb
135
149
  - lib/timescale/acts_as_hypertable.rb
150
+ - lib/timescale/acts_as_hypertable/core.rb
136
151
  - lib/timescale/chunk.rb
137
152
  - lib/timescale/compression_settings.rb
138
153
  - lib/timescale/continuous_aggregates.rb