Class: NodeTask

Inherits:
Object
  • Object
show all
Defined in:
lib/node_task/node_task.rb

Defined Under Namespace

Classes: Error

Constant Summary collapse

RESPONSE_TIMEOUT =
9999
START_MAX_RETRIES =
1

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(_task) ⇒ NodeTask

Returns a new instance of NodeTask.



256
257
258
# File 'lib/node_task/node_task.rb', line 256

def initialize(_task)
  @task = _task
end

Class Attribute Details

.loggerObject



36
37
38
39
40
41
# File 'lib/node_task/node_task.rb', line 36

def logger
  return @logger unless @logger.nil?
  @logger = Logger.new(STDERR)
  @logger.level = ENV["NODE_TASK_DEBUG"] ? Logger::DEBUG : Logger::INFO 
  @logger
end

.node_commandObject



67
68
69
# File 'lib/node_task/node_task.rb', line 67

def node_command
  @node_command || ENV["NODE_COMMAND"] || 'node'
end

.working_dirObject



43
44
45
# File 'lib/node_task/node_task.rb', line 43

def working_dir
  @working_dir || Dir.pwd
end

Instance Attribute Details

#taskObject

Returns the value of attribute task.



254
255
256
# File 'lib/node_task/node_task.rb', line 254

def task
  @task
end

Class Method Details

.alive?Boolean

Returns:

  • (Boolean)


163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/node_task/node_task.rb', line 163

def alive?
  current_pid = nil
  alive = false
  if @controller
    begin
      current_pid = @controller.pid
    rescue Errno::ENOENT
    end
  end
  if current_pid
    begin
      Process.getpgid(current_pid)
      alive = true
    rescue Errno::ESRCH
    end
  end
  alive
end

.check_errorObject



117
118
119
120
121
122
123
124
# File 'lib/node_task/node_task.rb', line 117

def check_error
  if File.exist? error_log_file
    # TODO: raise error
    logger.error File.open(error_log_file).read
    File.unlink error_log_file
    true
  end
end

.daemon_envObject



196
197
198
199
200
201
202
203
204
205
# File 'lib/node_task/node_task.rb', line 196

def daemon_env
  {
    "NODE_TASK_SOCK_PATH" => socket_path,
    "NODE_TASK_CWD" => working_dir,
    "NODE_TASK_DAEMON_ID" => daemon_identifier,
    "NODE_TASK_PARENT_PID" => Process.pid.to_s,
    "NODE_TASK_PARENT_CHECK_INTERVAL" => parent_check_interval.to_s,
    "NODE_ENV" => ENV["RACK_ENV"],
  }
end

.daemon_identifierObject



59
60
61
# File 'lib/node_task/node_task.rb', line 59

def daemon_identifier
  'ruby_node_task'
end

.daemon_start_scriptObject



71
72
73
# File 'lib/node_task/node_task.rb', line 71

def daemon_start_script
  File.join(gem_dir, 'nodeTask.js').to_s
end

.ensure_connectionObject

really try to successfully connect, starting the daemon if required



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/node_task/node_task.rb', line 90

def ensure_connection
  attempt = 0
  begin
    server # make sure daemon is running

    socket = server.connect do
      begin
        _make_connection
      rescue Errno::ENOENT => e 
        # daemon_controller doesn't understand ENOENT
        raise Errno::ECONNREFUSED, e.message
      end
    end
  rescue DaemonController::StartTimeout, DaemonController::StartError => e
    logger.error e.message
    if attempt < START_MAX_RETRIES
      attempt += 1
      logger.error "retrying attempt #{attempt}"
      retry
    else
      raise e
    end
  end

  socket
end

.error_log_fileObject



47
48
49
# File 'lib/node_task/node_task.rb', line 47

def error_log_file
  File.join(working_dir, "#{daemon_identifier}-error.log")
end

.gem_dirObject



55
56
57
# File 'lib/node_task/node_task.rb', line 55

def gem_dir
  @gem_dir ||= File.dirname(File.expand_path(__FILE__))
end

.parent_check_intervalObject



207
208
209
# File 'lib/node_task/node_task.rb', line 207

def parent_check_interval
  1000
end

.parse_response(socket) ⇒ Object

get a json response from socket



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/node_task/node_task.rb', line 127

def parse_response(socket)
  # only take one message - the result
  # response terminated by newline
  response_text = nil
  loop do
    response_text = socket.gets("\n")
    break if response_text
    break if check_error
  end
  if response_text
    JSON.parse(response_text, symbolize_names: true)
  else
    logger.error 'no response for message'
    nil
  end
end

.pid_fileObject



51
52
53
# File 'lib/node_task/node_task.rb', line 51

def pid_file
  File.join(working_dir, "#{daemon_identifier}.pid")
end

.releaseObject

stop the daemon



183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/node_task/node_task.rb', line 183

def release
  return unless alive?

  logger.debug "stopping daemon #{@controller.pid}"
  @controller.stop

  begin
    File.unlink socket_path
  rescue Errno::ENOENT => e
    # socket file's already gone
  end
end

.request(socket, message) ⇒ Object

make a single request, get a response and close the connection



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/node_task/node_task.rb', line 145

def request(socket, message)
  socket.write(message.to_json+"\n")

  result = nil
  begin
    Timeout::timeout(RESPONSE_TIMEOUT) do
      result = parse_response(socket)
    end
  rescue Timeout::Error, Exception => e
    logger.error e.message
  ensure
    # disconnect after receiving response
    socket.close
  end

  result
end

.serverObject

get configured daemon controller for daemon, and start it



76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/node_task/node_task.rb', line 76

def server
  @controller ||= _make_daemon_controller

  begin
    @controller.start
    logger.debug "spawned server #{@controller.pid}"
  rescue DaemonController::AlreadyStarted => e
    logger.debug "server already running #{@controller.pid}"
  end

  @controller
end

.socket_pathObject



63
64
65
# File 'lib/node_task/node_task.rb', line 63

def socket_path
  @socket_path ||= _make_sock_path(working_dir, daemon_identifier)
end

.windows?Boolean

Returns:

  • (Boolean)


32
33
34
# File 'lib/node_task/node_task.rb', line 32

def windows?
  (/cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM) != nil
end

Instance Method Details

#run(opts = nil) ⇒ Object



260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
# File 'lib/node_task/node_task.rb', line 260

def run(opts = nil)
  socket = self.class.ensure_connection

  message = {
    task: task,
    opts: opts,
  }

  response = self.class.request(socket, message)
  if response
    if response[:error]
      raise NodeTask::Error, response[:error]
    else
      response[:result]
    end
  end
end