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

Sign up to get free protection for your applications and to get access to all the features.
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