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.



250
251
252
# File 'lib/node_task/node_task.rb', line 250

def initialize(_task)
  @task = _task
end

Class Attribute Details

.loggerObject



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

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



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

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

.working_dirObject



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

def working_dir
  @working_dir || Dir.pwd
end

Instance Attribute Details

#taskObject

Returns the value of attribute task.



248
249
250
# File 'lib/node_task/node_task.rb', line 248

def task
  @task
end

Class Method Details

.check_errorObject



112
113
114
115
116
117
118
119
# File 'lib/node_task/node_task.rb', line 112

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

.clients_activeObject

number of connections active to the daemon



159
160
161
162
163
164
165
# File 'lib/node_task/node_task.rb', line 159

def clients_active
  socket = _make_connection # might fail
  message = {status: true} # special message type
  result = request(socket, message)
  return 0 if result.nil?
  result[:clients]
end

.daemon_identifierObject



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

def daemon_identifier
  'ruby_node_task'
end

.daemon_start_scriptObject



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

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

.ensure_connectionObject

really try to successfully connect, starting the daemon if required



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/node_task/node_task.rb', line 85

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



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

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

.gem_dirObject



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

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

.parse_response(socket) ⇒ Object

get a json response from socket



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/node_task/node_task.rb', line 122

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



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

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

.releaseObject

stop the daemon if no one else is using it



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/node_task/node_task.rb', line 168

def release
  begin
    # this doesn't really work as intended right now
    # as no connections are maintained when tasks aren't running
    return if clients_active > 0
  rescue Errno::ENOENT => e
    # socket file probably doesn't exist
    # maybe we should just return here?
  end

  pid = nil
  begin
    pid = @controller.pid
  rescue Errno::ENOENT => e
    # presumably no pid file exists and the daemon is not running
    logger.debug "daemon already stopped"
    return
  end

  logger.debug "stopping daemon #{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



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/node_task/node_task.rb', line 140

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



71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/node_task/node_task.rb', line 71

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



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

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

.windows?Boolean

Returns:

  • (Boolean)


27
28
29
# File 'lib/node_task/node_task.rb', line 27

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

Instance Method Details

#run(opts = nil) ⇒ Object



254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
# File 'lib/node_task/node_task.rb', line 254

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