File: polling.rb

package info (click to toggle)
ruby-spring 2.1.1-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 428 kB
  • sloc: ruby: 3,373; sh: 9; makefile: 7
file content (98 lines) | stat: -rw-r--r-- 2,255 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
require "spring/watcher/abstract"

module Spring
  module Watcher
    class Polling < Abstract
      attr_reader :mtime

      def initialize(root, latency)
        super
        @mtime  = 0
        @poller = nil
      end

      def check_stale
        synchronize do
          computed = compute_mtime
          if mtime < computed
            debug { "check_stale: mtime=#{mtime.inspect} < computed=#{computed.inspect}" }
            mark_stale
          end
        end
      end

      def add(*)
        check_stale if @poller
        super
      end

      def start
        debug { "start: poller=#{@poller.inspect}" }
        unless @poller
          @poller = Thread.new {
            Thread.current.abort_on_exception = true

            begin
              until stale?
                Kernel.sleep latency
                check_stale
              end
            rescue Exception => e
              debug do
                "poller: aborted: #{e.class}: #{e}\n  #{e.backtrace.join("\n  ")}"
              end
              raise
            ensure
              @poller = nil
            end
          }
        end
      end

      def stop
        debug { "stopping poller: #{@poller.inspect}" }
        if @poller
          @poller.kill
          @poller = nil
        end
      end

      def running?
        @poller && @poller.alive?
      end

      def subjects_changed
        computed = compute_mtime
        debug { "subjects_changed: mtime #{@mtime} -> #{computed}" }
        @mtime = computed
      end

      private

      def compute_mtime
        expanded_files.map do |f|
          # Get the mtime of symlink targets. Ignore dangling symlinks.
          if File.symlink?(f)
            begin
              File.mtime(f)
            rescue Errno::ENOENT
              0
            end
          # If a file no longer exists, treat it as changed.
          else
            begin
              File.mtime(f)
            rescue Errno::ENOENT
              debug { "compute_mtime: no longer exists: #{f}" }
              Float::MAX
            end
          end.to_f
        end.max || 0
      end

      def expanded_files
        files + Dir["{#{directories.map { |d| "#{d}/**/*" }.join(",")}}"]
      end
    end
  end
end