Module: Hyperloop

Defined in:
lib/hyper-operation/transport/hyperloop.rb,
lib/hyper-operation/api.rb,
lib/hyper-operation/boot.rb,
lib/hyper-operation/http.rb,
lib/hyper-operation/engine.rb,
lib/hyper-operation/railway.rb,
lib/hyper-operation/version.rb,
lib/hyper-operation/exception.rb,
lib/hyper-operation/server_op.rb,
lib/hyper-operation/railway/run.rb,
lib/hyper-operation/transport/policy.rb,
lib/hyper-operation/railway/dispatcher.rb,
lib/hyper-operation/filters/acting_user.rb,
lib/hyper-operation/railway/validations.rb,
lib/hyper-operation/transport/connection.rb,
lib/hyper-operation/railway/params_wrapper.rb,
lib/hyper-operation/transport/action_cable.rb,
lib/hyper-operation/transport/client_drivers.rb,
lib/hyper-operation/transport/hyperloop_controller.rb

Overview

this is going to need some refactoring so that HyperMesh can add its methods in hereā€¦

Defined Under Namespace

Modules: AutoConnect, AutoCreate, ClassPolicyMethods, PolicyAutoLoader, PolicyMethods Classes: AccessViolation, ActingUser, ActionCableChannel, Application, ChannelBroadcastRegulation, ClassConnectionRegulation, ClientDrivers, Connection, ControllerOp, Engine, HTTP, IncomingBroadcast, InstanceBroadcastRegulation, InstanceConnectionRegulation, InternalClassPolicy, InternalPolicy, Operation, Regulation, SendSet, ServerOp

Class Method Summary collapse

Class Method Details

.action_cable_consumerObject


52
53
54
# File 'lib/hyper-operation/transport/client_drivers.rb', line 52

def self.action_cable_consumer
  ClientDrivers.opts[:action_cable_consumer]
end

.app_idObject


67
68
69
# File 'lib/hyper-operation/transport/hyperloop.rb', line 67

def self.app_id
  opts[:app_id] || Pusher.app_id if transport == :pusher
end

.authorization(salt, channel, session_id) ⇒ Object


145
146
147
148
149
150
# File 'lib/hyper-operation/transport/hyperloop.rb', line 145

def self.authorization(salt, channel, session_id)
  secret_key = Rails.application.secrets[:secret_key_base]
  Digest::SHA1.hexdigest(
    "salt: #{salt}, channel: #{channel}, session_id: #{session_id}, secret_key: #{secret_key}"
  )
end

.channelObject


141
142
143
# File 'lib/hyper-operation/transport/hyperloop.rb', line 141

def self.channel
  "private-#{channel_prefix}"
end

.clusterObject


79
80
81
82
# File 'lib/hyper-operation/transport/hyperloop.rb', line 79

def self.cluster
  # mt1 is the default Pusher app cluster
  opts[:cluster] || 'mt1' if transport == :pusher
end

.connect(*channels) ⇒ Object


34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/hyper-operation/transport/client_drivers.rb', line 34

def self.connect(*channels)
  channels.each do |channel|
    if channel.is_a? Class
      IncomingBroadcast.connect_to(channel.name)
    elsif channel.is_a?(String) || channel.is_a?(Array)
      IncomingBroadcast.connect_to(*channel)
    elsif channel.id
      IncomingBroadcast.connect_to(channel.class.name, channel.id)
    else
      raise "cannot connect to model before it has been saved"
    end
  end
end

.connect_sessionObject


48
49
50
# File 'lib/hyper-operation/transport/client_drivers.rb', line 48

def self.connect_session
  connect(['Hyperloop::Session', ClientDrivers.opts[:id].split('-').last])
end

.dispatch(data) ⇒ Object


169
170
171
172
173
174
175
# File 'lib/hyper-operation/transport/hyperloop.rb', line 169

def self.dispatch(data)
  if !Hyperloop.on_server? && Connection.root_path
    Hyperloop.send_to_server(data[:channel], [:dispatch, data])
  else
    Connection.send_to_channel(data[:channel], [:dispatch, data])
  end
end

.encryptedObject


84
85
86
# File 'lib/hyper-operation/transport/hyperloop.rb', line 84

def self.encrypted
  opts.key?(:encrypted) ? opts[:encrypted] : true
end

.expire_new_connection_inObject


96
97
98
# File 'lib/hyper-operation/transport/hyperloop.rb', line 96

def self.expire_new_connection_in
  opts[:expire_new_connection_in] || 10.seconds
end

.expire_polled_connection_inObject


88
89
90
# File 'lib/hyper-operation/transport/hyperloop.rb', line 88

def self.expire_polled_connection_in
  opts[:expire_polled_connection_in] || (5 * 60)
end

.initialize_policiesObject


5
6
7
# File 'lib/hyper-operation/transport/hyperloop.rb', line 5

def self.initialize_policies
  reset_operations unless @config_reset_called
end

.keyObject


71
72
73
# File 'lib/hyper-operation/transport/hyperloop.rb', line 71

def self.key
  opts[:key] || Pusher.key if transport == :pusher
end

.on_server?Boolean

Returns:

  • (Boolean)

124
125
126
# File 'lib/hyper-operation/transport/hyperloop.rb', line 124

def self.on_server?
  return defined? Rails::Server
end

.pusherObject


128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/hyper-operation/transport/hyperloop.rb', line 128

def self.pusher
  unless @pusher
    unless channel_prefix
      self.transport = nil
      raise '******** NO CHANNEL PREFIX SET ***************'
    end
    @pusher = Pusher::Client.new(
      opts || { app_id: app_id, key: key, secret: secret, cluster: cluster }
    )
  end
  @pusher
end

.refresh_channelsObject


108
109
110
111
112
# File 'lib/hyper-operation/transport/hyperloop.rb', line 108

def self.refresh_channels
  new_channels = pusher.channels[:channels].collect do |channel, _etc|
    channel.gsub(/^#{Regexp.quote(Hyperloop.channel)}\-/, '').gsub('==', '::')
  end
end

.refresh_channels_everyObject


104
105
106
# File 'lib/hyper-operation/transport/hyperloop.rb', line 104

def self.refresh_channels_every
  opts[:refresh_channels_every] || 2.minutes
end

.refresh_channels_timeoutObject


100
101
102
# File 'lib/hyper-operation/transport/hyperloop.rb', line 100

def self.refresh_channels_timeout
  opts[:refresh_channels_timeout] || 5.seconds
end

.reset_operationsObject


13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/hyper-operation/transport/hyperloop.rb', line 13

def self.reset_operations
  @config_reset_called = true
  Rails.configuration.tap do |config|
    # config.eager_load_paths += %W(#{config.root}/app/hyperloop/models)
    # config.autoload_paths += %W(#{config.root}/app/hyperloop/models)
    # config.assets.paths << ::Rails.root.join('app', 'hyperloop').to_s
    config.after_initialize { Connection.build_tables }
  end
  Object.send(:remove_const, :Application) if @fake_application_defined
  @fake_application_defined = false
  policy = begin
    Object.const_get 'ApplicationPolicy'
  rescue LoadError
  rescue NameError => e
    raise e unless e.message =~ /uninitialized constant ApplicationPolicy/
  end
  application = begin
    Object.const_get('Application')
  rescue LoadError
  rescue NameError => e
    raise e unless e.message =~ /uninitialized constant Application/
  end if policy
  if policy && !application
    Object.const_set 'Application', Class.new
    @fake_application_defined = true
  end
  begin
    Object.const_get 'Hyperloop::ApplicationPolicy'
  rescue LoadError
  rescue NameError => e
    raise e unless e.message =~ /uninitialized constant Hyperloop::ApplicationPolicy/
  end
  @pusher = nil
end

.seconds_between_pollObject


92
93
94
# File 'lib/hyper-operation/transport/hyperloop.rb', line 92

def self.seconds_between_poll
  opts[:seconds_between_poll] || 0.5
end

.secretObject


75
76
77
# File 'lib/hyper-operation/transport/hyperloop.rb', line 75

def self.secret
  opts[:secret] || Pusher.secret if transport == :pusher
end

.send_data(channel, data) ⇒ Object


114
115
116
117
118
119
120
121
122
# File 'lib/hyper-operation/transport/hyperloop.rb', line 114

def self.send_data(channel, data)
  if !on_server?
    send_to_server(channel, data)
  elsif transport == :pusher
    pusher.trigger("#{Hyperloop.channel}-#{data[1][:channel].gsub('::', '==')}", *data)
  elsif transport == :action_cable
    ActionCable.server.broadcast("hyperloop-#{channel}", message: data[0], data: data[1])
  end
end

.send_to_server(channel, data) ⇒ Object

TODO this should work the same/similar to HyperMesh / Models way of sending to console


152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/hyper-operation/transport/hyperloop.rb', line 152

def self.send_to_server(channel, data) # TODO this should work the same/similar to HyperMesh / Models way of sending to console
  salt = SecureRandom.hex
  authorization = authorization(salt, channel, data[1][:broadcast_id])
  raise 'no server running' unless Connection.root_path
  uri = URI("#{Connection.root_path}console_update")
  http = Net::HTTP.new(uri.host, uri.port)
  request = Net::HTTP::Post.new(uri.path, 'Content-Type' => 'application/json')
  if uri.scheme == 'https'
    http.use_ssl = true
    http.verify_mode = OpenSSL::SSL::VERIFY_NONE
  end
  request.body = {
    channel: channel, data: data, salt: salt, authorization: authorization
  }.to_json
  http.request(request)
end