Class: Ruflet::HotReload::Runner

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(script:, watch_root: nil, poll_interval: DEFAULT_POLL_INTERVAL, server_factory: nil, logger: nil) ⇒ Runner

Returns a new instance of Runner.

Raises:



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/ruflet/hot_reload.rb', line 43

def initialize(script:, watch_root: nil, poll_interval: DEFAULT_POLL_INTERVAL, server_factory: nil, logger: nil)
  @script = File.expand_path(script)
  raise Error, "script not found: #{@script}" unless File.file?(@script)

  root = watch_root.to_s.empty? ? File.dirname(@script) : watch_root
  @watch_root = File.expand_path(root)
  @poll_interval = poll_interval
  @server_factory = server_factory
  @logger = logger
  @current_block = nil
  @server = nil
  @watcher = nil
  @reload_count = 0
  @force_reload = false
  @reload_mutex = Mutex.new
end

Instance Attribute Details

#current_blockObject (readonly)

Returns the value of attribute current_block.



41
42
43
# File 'lib/ruflet/hot_reload.rb', line 41

def current_block
  @current_block
end

#reload_countObject (readonly)

Returns the value of attribute reload_count.



41
42
43
# File 'lib/ruflet/hot_reload.rb', line 41

def reload_count
  @reload_count
end

#serverObject (readonly)

Returns the value of attribute server.



41
42
43
# File 'lib/ruflet/hot_reload.rb', line 41

def server
  @server
end

Instance Method Details

#reload!Object



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

def reload!
  @reload_mutex.synchronize do
    started = Process.clock_gettime(Process::CLOCK_MONOTONIC)
    begin
      prune_watched_features!
      load_script!
      if @server.respond_to?(:reload_app!)
        @server.reload_app!
      else
        log "installed ruflet_server does not support reload_app!; clients keep the previous UI"
      end
      @reload_count += 1
      elapsed_ms = ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - started) * 1000).round
      log "reloaded in #{elapsed_ms}ms"
    rescue Exception => e # rubocop:disable Lint/RescueException -- a broken script must never kill the dev loop
      raise if fatal_error?(e)

      log "reload failed: #{e.class}: #{e.message}"
      Array(e.backtrace).first(3).each { |line| log "  #{line}" }
    end
  end
end

#request_reloadObject



86
87
88
# File 'lib/ruflet/hot_reload.rb', line 86

def request_reload
  @force_reload = true
end

#runObject



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/ruflet/hot_reload.rb', line 60

def run
  unless Ruflet.respond_to?(:with_run_interceptor)
    log "installed ruflet_core does not support run interceptors; running without hot reload"
    return load_script!
  end

  Ruflet.with_run_interceptor(run_interceptor) do
    load_script!
    raise Error, "#{@script} never called Ruflet.run" unless @server

    @snapshot = file_snapshot
    start_watcher
    install_manual_reload_trap
    @server.start
  end
end

#stopObject



77
78
79
80
# File 'lib/ruflet/hot_reload.rb', line 77

def stop
  @watcher&.kill
  @watcher = nil
end

#watched_filesObject



113
114
115
116
117
# File 'lib/ruflet/hot_reload.rb', line 113

def watched_files
  files = Dir.glob(File.join(@watch_root, "**", "*.rb")).reject { |path| excluded_path?(path) }
  files << @script unless files.include?(@script) || !File.file?(@script)
  files
end

#watching?Boolean

Returns:

  • (Boolean)


82
83
84
# File 'lib/ruflet/hot_reload.rb', line 82

def watching?
  !@watcher.nil?
end