locked_process 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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