locked_process 0.0.1

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.
data/README.md ADDED
@@ -0,0 +1,26 @@
1
+ # LockedProcess
2
+ Locked process is a way of executing a Thread but preventing the same Thread from being executed while the first one is still running.
3
+
4
+ ## Instalation
5
+ ```bash
6
+ gem install 'locked_process'
7
+ ```
8
+
9
+ ## Usage
10
+ ```ruby
11
+ require 'locked_process'
12
+
13
+ process = LockedProcess.new('/tmp/download_images.pid') do
14
+ MyImageDownloader.new.download
15
+ end
16
+
17
+ process.execute # executes MyImageDownloader.new.download in a Thread
18
+
19
+ # if the process is still running
20
+ process.execute # raises LockedProcess::Error
21
+
22
+ ```
23
+
24
+
25
+ ## Author
26
+ Marcelo Jacobus
@@ -0,0 +1,42 @@
1
+ require 'thread'
2
+
3
+ class LockedProcess
4
+ VERSION = '0.0.1'
5
+
6
+ class Error < StandardError; end
7
+
8
+ attr_reader :pid_file
9
+
10
+ def initialize(pid_file)
11
+ unless block_given?
12
+ raise ArgumentError.new('Block must be given')
13
+ end
14
+
15
+ @process = lambda { yield }
16
+ @pid_file = pid_file
17
+ end
18
+
19
+ def pid_file_exists?
20
+ File.exists?(pid_file)
21
+ end
22
+
23
+ def execute
24
+ create_pid_file
25
+ Thread.new do
26
+ @process.call
27
+ remove_pid_file
28
+ end
29
+ end
30
+
31
+ private
32
+ def create_pid_file
33
+ if pid_file_exists?
34
+ raise Error.new("Process is already running (pidfile '#{pid_file}' exists)")
35
+ end
36
+ File.open(pid_file, 'w').close
37
+ end
38
+
39
+ def remove_pid_file
40
+ File.unlink(pid_file)
41
+ end
42
+ end
@@ -0,0 +1,88 @@
1
+ require 'spec_helper'
2
+
3
+ describe LockedProcess do
4
+ before do
5
+ system("rm -f #{pidfile}")
6
+ system("rm -f #{test_file}")
7
+ end
8
+
9
+ after do
10
+ system("rm -f #{pidfile}")
11
+ system("rm -f #{test_file}")
12
+ end
13
+
14
+ let(:mocked) { mock(:mocked, run: 'running') }
15
+ let(:pidfile) { '/tmp/locked_process_spec.pid' }
16
+ let(:test_file) { '/tmp/locked_process_test_file.pid' }
17
+
18
+ subject do
19
+ LockedProcess.new(pidfile) do
20
+ mocked.run('abc')
21
+ end
22
+ end
23
+
24
+
25
+ describe "#initialize" do
26
+ context "when block is not given" do
27
+ it "raises ArgumentError" do
28
+ expect { LockedProcess.new(pidfile) }.to raise_error(ArgumentError, 'Block must be given')
29
+ end
30
+ end
31
+ end
32
+
33
+ describe "#execute" do
34
+ it "creates a pid file" do
35
+ subject.execute
36
+ File.exists?(pidfile).should be_true
37
+ end
38
+
39
+ it "raises an exception when file exists" do
40
+ subject.stub(:pid_file_exists?).and_return(true)
41
+ expect { subject.execute }.to raise_error(LockedProcess::Error, "Process is already running (pidfile '#{pidfile}' exists)")
42
+ end
43
+
44
+ it "executes the code in a thread and removes the pid file" do
45
+ process = LockedProcess.new(pidfile) do
46
+ sleep(0.1)
47
+ File.open(test_file, 'w').close
48
+ end
49
+
50
+ process.execute
51
+
52
+ File.exists?(test_file).should be_false
53
+ File.exists?(pidfile).should be_true
54
+ sleep(0.2)
55
+ File.exists?(test_file).should be_true
56
+ File.exists?(pidfile).should be_false
57
+ end
58
+
59
+ it "executes even if the main process is gone down" do
60
+ process = LockedProcess.new(pidfile) do
61
+ sleep(0.1)
62
+ File.open(test_file, 'w').close
63
+ end
64
+
65
+ process.execute
66
+
67
+ fork do
68
+ exit
69
+ end
70
+
71
+ File.exists?(test_file).should be_false
72
+ File.exists?(pidfile).should be_true
73
+ sleep(0.2)
74
+ File.exists?(test_file).should be_true
75
+ File.exists?(pidfile).should be_false
76
+
77
+ end
78
+ end
79
+
80
+ describe "#pid_file_exists?" do
81
+ it "checks whether pid file exists" do
82
+ subject.pid_file_exists?.should be_false
83
+ system("touch #{pidfile}")
84
+ subject.pid_file_exists?.should be_true
85
+ end
86
+ end
87
+
88
+ end
@@ -0,0 +1,15 @@
1
+ require 'simplecov'
2
+
3
+ SimpleCov.start do
4
+ add_filter "spec"
5
+ end
6
+
7
+ require 'locked_process'
8
+
9
+ Dir["./spec/support/**/*.rb"].each {|f| require f}
10
+
11
+ RSpec.configure do |config|
12
+ config.treat_symbols_as_metadata_keys_with_true_values = true
13
+ config.filter_run :focus => true
14
+ config.run_all_when_everything_filtered = true
15
+ end
data/spec/test.rb ADDED
@@ -0,0 +1,17 @@
1
+ $:.push File.expand_path("../../lib", __FILE__)
2
+
3
+ require 'locked_process'
4
+
5
+ file = '/tmp/locked_process_test_file.txt'
6
+ pidfile = '/tmp/locked_process_test_file_pid.pid'
7
+
8
+ File.unlink(file) if File.exists?(file)
9
+ #File.unlink(pidfile) if File.exists?(pidfile)
10
+
11
+ process = LockedProcess.new(pidfile) do
12
+ sleep 2
13
+ File.open(file, 'w').close
14
+ sleep 2
15
+ end
16
+
17
+ process.execute
metadata ADDED
@@ -0,0 +1,117 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: locked_process
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Marcelo Jacobus
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-04-26 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: simplecov
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: guard-rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rb-inotify
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ description: Trhead process that only executes if no other thread with the same lock
79
+ file is running
80
+ email: marcelo.jacobus@gmail.com
81
+ executables: []
82
+ extensions: []
83
+ extra_rdoc_files: []
84
+ files:
85
+ - README.md
86
+ - lib/locked_process.rb
87
+ - spec/test.rb
88
+ - spec/spec_helper.rb
89
+ - spec/lib/locked_process_spec.rb
90
+ homepage: https://github.com/mjacobus/locked_process
91
+ licenses: []
92
+ post_install_message:
93
+ rdoc_options: []
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ none: false
104
+ requirements:
105
+ - - ! '>='
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubyforge_project:
110
+ rubygems_version: 1.8.24
111
+ signing_key:
112
+ specification_version: 3
113
+ summary: Thread process with that can run only if it is unique
114
+ test_files:
115
+ - spec/test.rb
116
+ - spec/spec_helper.rb
117
+ - spec/lib/locked_process_spec.rb