rufus-daemon 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e223784d24bf2446f29d91e3828094d1146d629ccb5cf09fde6056e48a2f5d80
4
+ data.tar.gz: 154fb35fad31697e6e7f3aa4a4efc90cec18c82c6df7d1b77319f3b5a6b8433a
5
+ SHA512:
6
+ metadata.gz: 479f339eeae9f8c460d1cbbc5887bab1031314c745b87d76d8036dd73a244f2e501724f06f377e75e519bbf8adccc405eff728811e8bcc6a9f2a94aed62a9205
7
+ data.tar.gz: f7f153e94c0f41ebac64f686d78585602322415022559116ac91f62045c41cf731d96abde9136159b2d6c489b47bde46945411e39581b0d51ce8554e11d83b34
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ *.gem
11
+ *.rbc
12
+ .byebug_history
13
+ .DS_Store
14
+ Gemfile.lock
15
+
16
+ *.swp
17
+ *.swo
18
+ *~
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gemspec
6
+
7
+ group :development do
8
+ #gem "minitest", "~> 5.0"
9
+ #gem "rake", "~> 13.0"
10
+ #gem "rubocop", "~> 1.21"
11
+ #gem "yard", "~> 0.9"
12
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,55 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ mirrorfile (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ ast (2.4.3)
10
+ json (2.18.0)
11
+ language_server-protocol (3.17.0.5)
12
+ lint_roller (1.1.0)
13
+ minitest (5.27.0)
14
+ parallel (1.27.0)
15
+ parser (3.3.10.0)
16
+ ast (~> 2.4.1)
17
+ racc
18
+ prism (1.7.0)
19
+ racc (1.8.1)
20
+ rainbow (3.1.1)
21
+ rake (13.3.1)
22
+ regexp_parser (2.11.3)
23
+ rubocop (1.82.1)
24
+ json (~> 2.3)
25
+ language_server-protocol (~> 3.17.0.2)
26
+ lint_roller (~> 1.1.0)
27
+ parallel (~> 1.10)
28
+ parser (>= 3.3.0.2)
29
+ rainbow (>= 2.2.2, < 4.0)
30
+ regexp_parser (>= 2.9.3, < 3.0)
31
+ rubocop-ast (>= 1.48.0, < 2.0)
32
+ ruby-progressbar (~> 1.7)
33
+ unicode-display_width (>= 2.4.0, < 4.0)
34
+ rubocop-ast (1.49.0)
35
+ parser (>= 3.3.7.2)
36
+ prism (~> 1.7)
37
+ ruby-progressbar (1.13.0)
38
+ unicode-display_width (3.2.0)
39
+ unicode-emoji (~> 4.1)
40
+ unicode-emoji (4.2.0)
41
+ yard (0.9.38)
42
+
43
+ PLATFORMS
44
+ ruby
45
+ x86_64-linux
46
+
47
+ DEPENDENCIES
48
+ minitest (~> 5.0)
49
+ mirrorfile!
50
+ rake (~> 13.0)
51
+ rubocop (~> 1.21)
52
+ yard (~> 0.9)
53
+
54
+ BUNDLED WITH
55
+ 2.7.2
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2024 Your Name
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,75 @@
1
+ # rufus-daemon
2
+
3
+ Run a rufus-scheduler daemon in the background, with access to the instance over DRb unix socket.
4
+ Lovingly built to prevent hanging processes.
5
+
6
+ ## Why?
7
+ 1. Get status updates on your jobs
8
+ 2. Build a job querying service
9
+ 3. Allow other processes to dynamically schedule jobs
10
+ 4. Organise schedule files in ~/.rufus
11
+ 5. ???
12
+ 6. Profit
13
+
14
+ ## Install
15
+ ```ruby
16
+ gem install rufus-daemon
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ ### Running the command line
22
+ ```bash
23
+ $ rufus --help
24
+ Usage: rufus [options]
25
+
26
+ Example: rufus --start
27
+
28
+ Options:
29
+ --start
30
+ --restart
31
+ --stop
32
+ --status
33
+ --list
34
+
35
+ Help options:
36
+ --help
37
+ ```
38
+
39
+ ### Access the rufus instance over DRb socket
40
+ ```ruby
41
+ require 'rufus/daemon'
42
+
43
+ Rufus::Daemon.attach.then do |service|
44
+ puts service.rufus # the rufus-scheduler instance
45
+
46
+ # .jobs is a helper that deserializes the jobs before sending
47
+ # over DRb socket. Otherwise you get a marshalling error.
48
+ service.jobs.each do |job|
49
+ puts job
50
+ end
51
+ end
52
+ ```
53
+
54
+ ###
55
+ The daemon will load both a `~/rufus.rb` file, and all files inside `~/.rufus` with the glob `~/.rufus/**/*.rb`.
56
+ Here's what your files can look like.
57
+ ```
58
+ every '10s' do
59
+ # call something
60
+ end
61
+
62
+ cron '0 9 * * *' do
63
+ # call something
64
+ end
65
+ ```
66
+
67
+
68
+
69
+ ## Contributing
70
+
71
+ Bug reports and pull requests are welcome on GitHub.
72
+
73
+ ## License
74
+
75
+ The gem is available as open source under the terms of the [MIT License](LICENSE.txt).
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ #require "bundler/gem_tasks"
4
+ #require "rake/testtask"
5
+ #require "yard"
6
+ #
7
+ #Rake::TestTask.new(:test) do |t|
8
+ # t.libs << "test"
9
+ # t.libs << "lib"
10
+ # t.test_files = FileList["test/**/*_test.rb"]
11
+ #end
12
+ #
13
+ #YARD::Rake::YardocTask.new do |t|
14
+ # t.files = ["lib/**/*.rb"]
15
+ # t.options = ["--markup", "markdown"]
16
+ #end
17
+ #
18
+ #task default: :test
data/bin/console ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require_relative "../lib/rufus/daemon"
6
+ require "irb"
7
+
8
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
data/exe/rufus ADDED
@@ -0,0 +1,122 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require_relative '../lib/rufus/daemon'
5
+
6
+ #def install
7
+ # # install systemd service
8
+ # #
9
+ # File.write 'filename', <<~SERVICE
10
+ # what ever goes in a service file
11
+ # SERVICE
12
+ #end
13
+
14
+ SCHEDULE_FILE = File.expand_path("~/rufus.rb")
15
+ SCHEDULE_DIR = File.expand_path("~/.rufus")
16
+
17
+ # Your schedule file can look like this:
18
+ #
19
+ # every '10s' do
20
+ # puts "hello"
21
+ # end
22
+ #
23
+ # cron '0 9 * * *' do
24
+ # puts "morning"
25
+ # end
26
+
27
+ def start
28
+ Rufus::Daemon.start
29
+ sleep 1
30
+
31
+ if File.exist?(SCHEDULE_FILE)
32
+ Rufus::Daemon.attach.then do |daemon|
33
+ if daemon.jobs.empty?
34
+ daemon.load_schedule(SCHEDULE_FILE)
35
+ end
36
+ end
37
+ end
38
+
39
+ if Dir.exist?(SCHEDULE_DIR)
40
+ Rufus::Daemon.attach.then do |daemon|
41
+ if daemon.jobs.empty?
42
+ Dir.glob("#{SCHEDULE_DIR}/**/*.rb").each do |file|
43
+ daemon.load_schedule(file)
44
+ end
45
+ end
46
+ end
47
+ end
48
+ rescue DRb::DRbConnError
49
+ puts "Failed to connect after start"
50
+ puts "Therefore, couldn't load schedule"
51
+ end
52
+
53
+ def stop
54
+ Rufus::Daemon.stop
55
+ end
56
+
57
+ def restart
58
+ stop
59
+ sleep 1
60
+ start
61
+ end
62
+
63
+ def status
64
+ Rufus::Daemon.attach.rufus.then do |rufus|
65
+ puts "Total jobs: #{rufus.jobs.count}"
66
+ end
67
+ rescue DRb::DRbConnError => e
68
+ puts "Not started"
69
+ puts e
70
+ end
71
+
72
+ def list
73
+ Rufus::Daemon.attach.then do |rufus|
74
+ if rufus.jobs.any?
75
+ rufus.jobs.each do |job|
76
+ puts job
77
+ end
78
+ else
79
+ puts "No jobs"
80
+ end
81
+ end
82
+ rescue DRb::DRbConnError => e
83
+ puts "Not started"
84
+ puts e
85
+ end
86
+
87
+ OptionParser.new.instance_exec do
88
+ banner = 'Usage: rufus [options]'
89
+
90
+ separator ''
91
+ separator 'Example: rufus --start'
92
+
93
+ separator ''
94
+ separator 'Options:'
95
+
96
+ on('--install') { install; exit }
97
+ on('--start') { start; exit }
98
+ on('--restart') { restart; exit }
99
+ on('--stop') { stop; exit }
100
+ on('--status') { status; exit }
101
+ on('--list') { list; exit }
102
+
103
+ separator ''
104
+ separator 'Help options:'
105
+
106
+ on('--help') { puts self; exit }
107
+
108
+ if ARGV.empty?
109
+ puts self
110
+ else
111
+ case ARGV.first.to_sym
112
+ when :start then start
113
+ when :restart then restart
114
+ when :stop then stop
115
+ when :status then status
116
+ when :list then list
117
+ when :help then puts self
118
+ else
119
+ parse!
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'drb/drb'
4
+ require 'fileutils'
5
+ require 'rufus-scheduler'
6
+
7
+ module Rufus
8
+ class Daemon
9
+ VERSION = "1.0.0"
10
+
11
+ SOCKET_DIR = "/tmp/drb-sockets"
12
+ SOCKET_FILE = SOCKET_DIR + "/rufus.sock"
13
+ SOCKET_URI = "drbunix://#{SOCKET_FILE}"
14
+
15
+ attr_reader :rufus
16
+
17
+ def initialize
18
+ @rufus = Rufus::Scheduler.new
19
+ @drb = DRb.start_service(SOCKET_URI, self)
20
+ end
21
+
22
+ def uri = @drb.uri
23
+
24
+ def load_schedule(path)
25
+ @rufus.instance_eval(File.read(path))
26
+ end
27
+
28
+ def stop
29
+ @rufus.shutdown
30
+ ensure
31
+ DRb.stop_service
32
+ end
33
+
34
+ def jobs
35
+ @rufus.jobs.map do |job|
36
+ {
37
+ id: job.id,
38
+ scheduled_at: job.scheduled_at.to_s,
39
+ next_time: (job.next_time.to_s if job.respond_to?(:next_time)),
40
+ last_time: (job.last_time.to_s if job.respond_to?(:last_time)),
41
+ tags: job.tags,
42
+ original: job.original
43
+ }.compact
44
+ end
45
+ end
46
+
47
+ def self.attach
48
+ DRbObject.new_with_uri(SOCKET_URI)
49
+ end
50
+
51
+ def self.stop
52
+ attach.stop
53
+ puts "Rufus stopped"
54
+ rescue DRb::DRbConnError
55
+ puts "Already Stopped"
56
+ end
57
+
58
+ def self.start
59
+ FileUtils.mkdir_p(SOCKET_DIR)
60
+
61
+ fork do
62
+ Process.setsid
63
+
64
+ fork do
65
+ daemon = new
66
+ puts "Rufus started - #{daemon.uri}"
67
+ DRb.thread.join
68
+ rescue Errno::EADDRINUSE
69
+ puts "Already started"
70
+ end
71
+
72
+ exit # closes the process after DRb ends
73
+ end
74
+
75
+ Process.wait # no idea what this does
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/rufus/daemon"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "rufus-daemon"
7
+ spec.version = Rufus::Daemon::VERSION
8
+ spec.authors = ["Nathan Kidd"]
9
+ spec.email = ["nathankidd@hey.com"]
10
+
11
+ spec.summary = "Run rufus-scheduler in the background"
12
+
13
+ spec.description = <<~DESC
14
+ Run rufus-scheduler in the background with a DRb unix socket.
15
+ You can save schedule files in the ~/.rufus directory or as ~/rufus.rb
16
+ DESC
17
+
18
+ spec.homepage = "https://github.com/n-at-han-k/rufus-daemon"
19
+ spec.license = "MIT"
20
+ spec.required_ruby_version = ">= 3.2.0"
21
+
22
+ spec.metadata["homepage_uri"] = spec.homepage
23
+ spec.metadata["source_code_uri"] = spec.homepage
24
+ spec.metadata["documentation_uri"] = spec.homepage
25
+ spec.metadata["rubygems_mfa_required"] = "true"
26
+
27
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|data)/}) }
28
+ spec.bindir = "exe"
29
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
+ spec.require_paths = ["lib"]
31
+
32
+ #spec.add_development_dependency "minitest", "~> 5.0"
33
+ #spec.add_development_dependency "rake", "~> 13.0"
34
+ #spec.add_development_dependency "rubocop", "~> 1.21"
35
+ #spec.add_development_dependency "yard", "~> 0.9"
36
+ end
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rufus-daemon
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Nathan Kidd
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies: []
12
+ description: |
13
+ Run rufus-scheduler in the background with a DRb unix socket.
14
+ You can save schedule files in the ~/.rufus directory or as ~/rufus.rb
15
+ email:
16
+ - nathankidd@hey.com
17
+ executables:
18
+ - rufus
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - ".gitignore"
23
+ - Gemfile
24
+ - Gemfile.lock
25
+ - LICENSE.txt
26
+ - README.md
27
+ - Rakefile
28
+ - bin/console
29
+ - bin/setup
30
+ - exe/rufus
31
+ - lib/rufus/daemon.rb
32
+ - rufus-daemon.gemspec
33
+ homepage: https://github.com/n-at-han-k/rufus-daemon
34
+ licenses:
35
+ - MIT
36
+ metadata:
37
+ homepage_uri: https://github.com/n-at-han-k/rufus-daemon
38
+ source_code_uri: https://github.com/n-at-han-k/rufus-daemon
39
+ documentation_uri: https://github.com/n-at-han-k/rufus-daemon
40
+ rubygems_mfa_required: 'true'
41
+ rdoc_options: []
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: 3.2.0
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ requirements: []
55
+ rubygems_version: 3.6.7
56
+ specification_version: 4
57
+ summary: Run rufus-scheduler in the background
58
+ test_files: []