hyper-operation 1.0.alpha1.8 → 1.0.0.lap28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -7
  3. data/.travis.yml +9 -21
  4. data/CODE_OF_CONDUCT.md +49 -0
  5. data/DOCS-POLICIES.md +582 -0
  6. data/DOCS.md +869 -0
  7. data/Gemfile +1 -5
  8. data/LICENSE.txt +21 -0
  9. data/README.md +77 -0
  10. data/Rakefile +2 -1
  11. data/dciy.toml +3 -0
  12. data/hyper-operation.gemspec +15 -19
  13. data/lib/hyper-operation.rb +6 -10
  14. data/lib/hyper-operation/api.rb +4 -8
  15. data/lib/hyper-operation/boot.rb +2 -3
  16. data/lib/hyper-operation/delay_and_interval.rb +9 -0
  17. data/lib/hyper-operation/engine.rb +2 -2
  18. data/lib/hyper-operation/exception.rb +4 -30
  19. data/lib/hyper-operation/filters/acting_user.rb +1 -1
  20. data/lib/hyper-operation/http.rb +2 -2
  21. data/lib/hyper-operation/promise.rb +2 -32
  22. data/lib/hyper-operation/railway.rb +1 -1
  23. data/lib/hyper-operation/railway/dispatcher.rb +5 -8
  24. data/lib/hyper-operation/railway/params_wrapper.rb +2 -2
  25. data/lib/hyper-operation/railway/run.rb +49 -58
  26. data/lib/hyper-operation/railway/validations.rb +3 -10
  27. data/lib/hyper-operation/server_op.rb +20 -46
  28. data/lib/hyper-operation/transport/action_cable.rb +8 -8
  29. data/lib/hyper-operation/transport/client_drivers.rb +55 -96
  30. data/lib/hyper-operation/transport/connection.rb +136 -58
  31. data/lib/hyper-operation/transport/{hyperstack.rb → hyperloop.rb} +15 -28
  32. data/lib/hyper-operation/transport/{hyperstack_controller.rb → hyperloop_controller.rb} +53 -59
  33. data/lib/hyper-operation/transport/policy.rb +49 -50
  34. data/lib/hyper-operation/version.rb +2 -2
  35. data/lib/sources/{hyperstack → hyperloop}/pusher.js +0 -0
  36. metadata +73 -94
  37. data/lib/hyper-operation/async_sleep.rb +0 -23
  38. data/lib/hyper-operation/transport/connection_adapter/active_record.rb +0 -113
  39. data/lib/hyper-operation/transport/connection_adapter/active_record/auto_create.rb +0 -26
  40. data/lib/hyper-operation/transport/connection_adapter/active_record/connection.rb +0 -47
  41. data/lib/hyper-operation/transport/connection_adapter/active_record/queued_message.rb +0 -42
  42. data/lib/hyper-operation/transport/connection_adapter/redis.rb +0 -94
  43. data/lib/hyper-operation/transport/connection_adapter/redis/connection.rb +0 -85
  44. data/lib/hyper-operation/transport/connection_adapter/redis/queued_message.rb +0 -34
  45. data/lib/hyper-operation/transport/connection_adapter/redis/redis_record.rb +0 -158
  46. data/lib/hyper-operation/transport/policy_diagnostics.rb +0 -106
@@ -1,23 +0,0 @@
1
- module Hyperstack
2
- module AsyncSleep
3
- if RUBY_ENGINE == 'opal'
4
- def self.every(*args, &block)
5
- every(*args, &block)
6
- end
7
-
8
- def self.after(*args, &block)
9
- after(*args, &block)
10
- end
11
- else
12
- extend self
13
-
14
- def every(time, &block)
15
- Thread.new { loop { sleep time; block.call } }
16
- end
17
-
18
- def after(time, &block)
19
- Thread.new { sleep time; block.call }
20
- end
21
- end
22
- end
23
- end
@@ -1,113 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'active_record/connection'
4
- require_relative 'active_record/queued_message'
5
-
6
- module Hyperstack
7
- module ConnectionAdapter
8
- module ActiveRecord
9
- class << self
10
- def build_tables
11
- Connection.create_table(force: :cascade) do |t|
12
- t.string :channel
13
- t.string :session
14
- t.datetime :created_at
15
- t.datetime :expires_at
16
- t.datetime :refresh_at
17
- end
18
-
19
- QueuedMessage.create_table(force: :cascade) do |t|
20
- t.text :data
21
- t.integer :connection_id
22
- end
23
- end
24
-
25
- def transport
26
- Hyperstack::Connection.transport
27
- end
28
-
29
- def active
30
- # if table doesn't exist then we are either calling from within
31
- # a migration or from a console before the server has ever started
32
- # in these cases there are no channels so we return nothing
33
- return [] unless Connection.table_exists?
34
-
35
- if Hyperstack.on_server?
36
- Connection.expired.delete_all
37
- refresh_connections if Connection.needs_refresh?
38
- end
39
-
40
- Connection.all.pluck(:channel).uniq
41
- rescue ::ActiveRecord::StatementInvalid
42
- []
43
- end
44
-
45
- def open(channel, session = nil, root_path = nil)
46
- self.root_path = root_path
47
-
48
- Connection.find_or_create_by(channel: channel, session: session)
49
- end
50
-
51
- def send_to_channel(channel, data)
52
- Connection.pending_for(channel).each do |connection|
53
- QueuedMessage.create(data: data, hyperstack_connection: connection)
54
- end
55
-
56
- transport.send_data(channel, data) if Connection.exists?(channel: channel, session: nil)
57
- end
58
-
59
- def read(session, root_path)
60
- self.root_path = root_path
61
-
62
- Connection.where(session: session)
63
- .update_all(expires_at: Time.current + transport.expire_polled_connection_in)
64
-
65
- QueuedMessage.for_session(session).destroy_all.pluck(:data)
66
- end
67
-
68
- def connect_to_transport(channel, session, root_path)
69
- self.root_path = root_path
70
-
71
- if (connection = Connection.find_by(channel: channel, session: session))
72
- messages = connection.messages.pluck(:data)
73
- connection.destroy
74
- else
75
- messages = []
76
- end
77
-
78
- open(channel)
79
-
80
- messages
81
- end
82
-
83
- def disconnect(channel)
84
- Connection.find_by(channel: channel, session: nil).destroy
85
- end
86
-
87
- def root_path=(path)
88
- QueuedMessage.root_path = path if path
89
- end
90
-
91
- def root_path
92
- # if the QueuedMessage table doesn't exist then we are either calling from within
93
- # a migration or from a console before the server has ever started
94
- # in these cases there is no root path to the server
95
- QueuedMessage.root_path if QueuedMessage.table_exists?
96
- end
97
-
98
- def refresh_connections
99
- refresh_started_at = Time.current
100
- channels = transport.refresh_channels
101
- next_refresh = refresh_started_at + transport.refresh_channels_every
102
-
103
- channels.each do |channel|
104
- connection = Connection.find_by(channel: channel, session: nil)
105
- connection.update(refresh_at: next_refresh) if connection
106
- end
107
-
108
- Connection.inactive.delete_all
109
- end
110
- end
111
- end
112
- end
113
- end
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Hyperstack
4
- module ConnectionAdapter
5
- module ActiveRecord
6
- module AutoCreate
7
- def table_exists?
8
- # works with both rails 4 and 5 without deprecation warnings
9
- if connection.respond_to?(:data_sources)
10
- connection.data_sources.include?(table_name)
11
- else
12
- connection.tables.include?(table_name)
13
- end
14
- end
15
-
16
- def needs_init?
17
- Hyperstack.transport != :none && Hyperstack.on_server? && !table_exists?
18
- end
19
-
20
- def create_table(*args, &block)
21
- connection.create_table(table_name, *args, &block) if needs_init?
22
- end
23
- end
24
- end
25
- end
26
- end
@@ -1,47 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'auto_create'
4
-
5
- module Hyperstack
6
- module ConnectionAdapter
7
- module ActiveRecord
8
- class Connection < ::ActiveRecord::Base
9
- extend AutoCreate
10
-
11
- self.table_name = 'hyperstack_connections'
12
-
13
- do_not_synchronize
14
-
15
- has_many :messages,
16
- foreign_key: 'connection_id',
17
- class_name: 'Hyperstack::ConnectionAdapter::ActiveRecord::QueuedMessage',
18
- dependent: :destroy
19
-
20
- scope :expired,
21
- -> { where('expires_at IS NOT NULL AND expires_at < ?', Time.current) }
22
- scope :pending_for,
23
- ->(channel) { where(channel: channel).where('session IS NOT NULL') }
24
- scope :inactive,
25
- -> { where('session IS NULL AND refresh_at < ?', Time.current) }
26
-
27
- before_create do
28
- if session
29
- self.expires_at = Time.current + transport.expire_new_connection_in
30
- elsif transport.refresh_channels_every != :never
31
- self.refresh_at = Time.current + transport.refresh_channels_every
32
- end
33
- end
34
-
35
- class << self
36
- def needs_refresh?
37
- exists?(['refresh_at IS NOT NULL AND refresh_at < ?', Time.current])
38
- end
39
- end
40
-
41
- def transport
42
- Hyperstack::Connection.transport
43
- end
44
- end
45
- end
46
- end
47
- end
@@ -1,42 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'auto_create'
4
-
5
- module Hyperstack
6
- module ConnectionAdapter
7
- module ActiveRecord
8
- class QueuedMessage < ::ActiveRecord::Base
9
- extend AutoCreate
10
-
11
- self.table_name = 'hyperstack_queued_messages'
12
-
13
- do_not_synchronize
14
-
15
- serialize :data
16
-
17
- belongs_to :hyperstack_connection,
18
- class_name: 'Hyperstack::ConnectionAdapter::ActiveRecord::Connection',
19
- foreign_key: 'connection_id',
20
- optional: true
21
-
22
- scope :for_session,
23
- ->(session) { joins(:hyperstack_connection).where('session = ?', session) }
24
-
25
- # For simplicity we use QueuedMessage with connection_id 0
26
- # to store the current path which is used by consoles to
27
- # communicate back to the server. The belongs_to connection
28
- # therefore must be optional.
29
-
30
- default_scope { where('connection_id IS NULL OR connection_id != 0') }
31
-
32
- def self.root_path=(path)
33
- unscoped.find_or_create_by(connection_id: 0).update(data: path)
34
- end
35
-
36
- def self.root_path
37
- unscoped.find_or_create_by(connection_id: 0).data
38
- end
39
- end
40
- end
41
- end
42
- end
@@ -1,94 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'redis/connection'
4
- require_relative 'redis/queued_message'
5
-
6
- module Hyperstack
7
- module ConnectionAdapter
8
- module Redis
9
- class << self
10
- def transport
11
- Hyperstack::Connection.transport
12
- end
13
-
14
- def active
15
- if Hyperstack.on_server?
16
- Connection.expired.each(&:destroy)
17
- refresh_connections if Connection.needs_refresh?
18
- end
19
-
20
- Connection.all.map(&:channel).uniq
21
- end
22
-
23
- def open(channel, session = nil, root_path = nil)
24
- self.root_path = root_path
25
-
26
- Connection.find_or_create_by(channel: channel, session: session)
27
- end
28
-
29
- def send_to_channel(channel, data)
30
- Connection.pending_for(channel).each do |connection|
31
- QueuedMessage.create(connection_id: connection.id, data: data)
32
- end
33
-
34
- transport.send_data(channel, data) if Connection.exists?(channel: channel, session: nil)
35
- end
36
-
37
- def read(session, root_path)
38
- self.root_path = root_path
39
-
40
- Connection.where(session: session).each do |connection|
41
- connection.update(expires_at: Time.current + transport.expire_polled_connection_in)
42
- end
43
-
44
- messages = QueuedMessage.for_session(session)
45
- data = messages.map(&:data)
46
- messages.each(&:destroy)
47
- data
48
- end
49
-
50
- def connect_to_transport(channel, session, root_path)
51
- self.root_path = root_path
52
-
53
- if (connection = Connection.find_by(channel: channel, session: session))
54
- messages = connection.messages.map(&:data)
55
- connection.destroy
56
- else
57
- messages = []
58
- end
59
-
60
- open(channel)
61
-
62
- messages
63
- end
64
-
65
- def disconnect(channel)
66
- Connection.find_by(channel: channel, session: nil).destroy
67
- end
68
-
69
- def root_path=(path)
70
- QueuedMessage.root_path = path if path
71
- end
72
-
73
- def root_path
74
- QueuedMessage.root_path
75
- rescue
76
- nil
77
- end
78
-
79
- def refresh_connections
80
- refresh_started_at = Time.current
81
- channels = transport.refresh_channels
82
- next_refresh = refresh_started_at + transport.refresh_channels_every
83
-
84
- channels.each do |channel|
85
- connection = Connection.find_by(channel: channel, session: nil)
86
- connection.update(refresh_at: next_refresh) if connection
87
- end
88
-
89
- Connection.inactive.each(&:destroy)
90
- end
91
- end
92
- end
93
- end
94
- end
@@ -1,85 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'redis_record'
4
-
5
- module Hyperstack
6
- module ConnectionAdapter
7
- module Redis
8
- class Connection < RedisRecord::Base
9
- self.table_name = 'hyperstack:connections'
10
- self.column_names = %w[id channel session created_at expires_at refresh_at].freeze
11
-
12
- attr_accessor(*column_names.map(&:to_sym))
13
-
14
- class << self
15
- def transport
16
- Hyperstack::Connection.transport
17
- end
18
-
19
- def create(opts = {})
20
- opts.tap do |hash|
21
- if opts[:session]
22
- hash[:expires_at] = (Time.current + transport.expire_new_connection_in)
23
- elsif transport.refresh_channels_every != :never
24
- hash[:refresh_at] = (Time.current + transport.refresh_channels_every)
25
- end
26
-
27
- hash[:created_at] = Time.current
28
- end.to_a.flatten
29
-
30
- super(opts)
31
- end
32
-
33
- def inactive
34
- scope { |id| id if inactive?(id) }
35
- end
36
-
37
- def inactive?(id)
38
- get_dejsonized_attribute(id, :session).blank? &&
39
- get_dejsonized_attribute(id, :refresh_at).present? &&
40
- Time.zone.parse(get_dejsonized_attribute(id, :refresh_at)) < Time.current
41
- end
42
-
43
- def expired
44
- scope { |id| id if expired?(id) }
45
- end
46
-
47
- def expired?(id)
48
- get_dejsonized_attribute(id, :expires_at).present? &&
49
- Time.zone.parse(get_dejsonized_attribute(id, :expires_at)) < Time.current
50
- end
51
-
52
- def pending_for(channel)
53
- scope { |id| id if pending_for?(id, channel) }
54
- end
55
-
56
- def pending_for?(id, channel)
57
- get_dejsonized_attribute(id, :session).present? &&
58
- get_dejsonized_attribute(id, :channel) == channel
59
- end
60
-
61
- def needs_refresh?
62
- scope { |id| id if needs_refresh(id) }.any?
63
- end
64
-
65
- def needs_refresh(id)
66
- get_dejsonized_attribute(id, :refresh_at).present? &&
67
- Time.zone.parse(get_dejsonized_attribute(id, :refresh_at)) < Time.current
68
- end
69
- end
70
-
71
- def messages
72
- QueuedMessage.where(connection_id: id)
73
- end
74
-
75
- %i[created_at expires_at refresh_at].each do |attr|
76
- define_method(attr) do
77
- value = instance_variable_get(:"@#{attr}")
78
-
79
- value.is_a?(Time) ? value : Time.zone.parse(value)
80
- end
81
- end
82
- end
83
- end
84
- end
85
- end
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'redis_record'
4
-
5
- module Hyperstack
6
- module ConnectionAdapter
7
- module Redis
8
- class QueuedMessage < RedisRecord::Base
9
- self.table_name = 'hyperstack:queued_messages'
10
- self.column_names = %w[id data connection_id].freeze
11
-
12
- attr_accessor(*column_names.map(&:to_sym))
13
-
14
- class << self
15
- def for_session(session)
16
- Connection.where(session: session).map(&:messages).flatten
17
- end
18
-
19
- def root_path=(path)
20
- find_or_create_by(connection_id: 0).update(data: path)
21
- end
22
-
23
- def root_path
24
- find_or_create_by(connection_id: 0).data
25
- end
26
- end
27
-
28
- def connection
29
- Connection.find(connection_id)
30
- end
31
- end
32
- end
33
- end
34
- end