Class: Nonnative::Server

Inherits:
Runner
  • Object
show all
Defined in:
lib/nonnative/server.rb

Overview

Runtime runner that manages an in-process Ruby server.

A server runner:

  • starts a Ruby thread that runs #perform_start,
  • waits briefly (via the runner wait), and
  • participates in readiness/shutdown via TCP port checks orchestrated by Pool.

Concrete server implementations are expected to subclass Server and implement:

  • #perform_start (to bind/listen and begin serving), and
  • #perform_stop (to gracefully shut down).

#stop calls the stop hook once for every successfully constructed lifecycle, even if startup never created a worker thread. This lets rollback release resources acquired by a constructor.

The underlying configuration is a ConfigurationServer.

Direct Known Subclasses

GRPCServer, HTTPServer

Instance Method Summary collapse

Methods inherited from Runner

#name

Constructor Details

#initialize(service) ⇒ Server



24
25
26
27
28
29
# File 'lib/nonnative/server.rb', line 24

def initialize(service)
  super

  @timeout = Nonnative::Timeout.new(service.timeout)
  @cleanup_required = true
end

Instance Method Details

#startArray<(Integer, TrueClass)>

Starts the server thread if it is not already running.

A thread retained from a stop that exceeded its timeout is treated as not running, so a server can be restarted even if a prior #stop never observed that thread's actual termination.



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/nonnative/server.rb', line 40

def start
  unless thread&.alive?
    @error = nil
    @cleanup_required = true
    @thread = Thread.new do
      perform_start
    rescue StandardError => e
      @error = e
      raise
    end
    @thread.report_on_exception = true

    wait_start

    Nonnative.logger.info "started server '#{service.name}'"
  end

  [object_id, true]
end

#stopInteger, Array<(Integer, FalseClass)>

Stops the server if its current lifecycle still requires cleanup.

Calls #perform_stop even if startup never created a worker thread, then waits up to the configured timeout for any owned thread to finish. A thread that exceeds the timeout is terminated and reported through Pool. A later stop retries draining a retained thread without calling #perform_stop again.



69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/nonnative/server.rb', line 69

def stop
  owned_thread = thread
  return object_id unless @cleanup_required || owned_thread

  perform_cleanup
  stopped = drain_thread(owned_thread) == :drained
  wait_stop
  @thread = nil unless owned_thread&.alive?

  Nonnative.logger.info "stopped server '#{service.name}'" if stopped

  stopped ? object_id : [object_id, false]
end

#terminationString?

Describes how the server thread terminated before becoming ready, for lifecycle diagnostics.

Returns nil while the thread is still alive, so callers can distinguish a dead thread from a live server that merely missed its readiness window.



89
90
91
92
93
94
95
# File 'lib/nonnative/server.rb', line 89

def termination
  return if thread.nil? || thread.alive?

  return "server thread raised #{error.class}: #{error.message}" if error

  'server thread exited before readiness'
end