rocketjob 3.5.2 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +63 -1
  3. data/bin/rocketjob +1 -0
  4. data/bin/rocketjob_batch_perf +11 -0
  5. data/lib/rocket_job/batch.rb +32 -0
  6. data/lib/rocket_job/batch/callbacks.rb +40 -0
  7. data/lib/rocket_job/batch/io.rb +154 -0
  8. data/lib/rocket_job/batch/logger.rb +57 -0
  9. data/lib/rocket_job/batch/lower_priority.rb +54 -0
  10. data/lib/rocket_job/batch/model.rb +157 -0
  11. data/lib/rocket_job/batch/performance.rb +99 -0
  12. data/lib/rocket_job/batch/result.rb +8 -0
  13. data/lib/rocket_job/batch/results.rb +9 -0
  14. data/lib/rocket_job/batch/state_machine.rb +102 -0
  15. data/lib/rocket_job/batch/statistics.rb +88 -0
  16. data/lib/rocket_job/batch/tabular.rb +56 -0
  17. data/lib/rocket_job/batch/tabular/input.rb +123 -0
  18. data/lib/rocket_job/batch/tabular/output.rb +59 -0
  19. data/lib/rocket_job/batch/throttle.rb +91 -0
  20. data/lib/rocket_job/batch/throttle_running_slices.rb +53 -0
  21. data/lib/rocket_job/batch/worker.rb +288 -0
  22. data/lib/rocket_job/cli.rb +29 -7
  23. data/lib/rocket_job/config.rb +1 -1
  24. data/lib/rocket_job/extensions/mongoid/clients/options.rb +37 -0
  25. data/lib/rocket_job/extensions/mongoid/contextual/mongo.rb +17 -0
  26. data/lib/rocket_job/extensions/mongoid/factory.rb +4 -4
  27. data/lib/rocket_job/extensions/mongoid_5/clients/options.rb +38 -0
  28. data/lib/rocket_job/extensions/mongoid_5/contextual/mongo.rb +64 -0
  29. data/lib/rocket_job/extensions/mongoid_5/factory.rb +13 -0
  30. data/lib/rocket_job/jobs/on_demand_batch_job.rb +127 -0
  31. data/lib/rocket_job/jobs/performance_job.rb +18 -0
  32. data/lib/rocket_job/jobs/upload_file_job.rb +2 -5
  33. data/lib/rocket_job/plugins/document.rb +2 -8
  34. data/lib/rocket_job/plugins/job/persistence.rb +6 -4
  35. data/lib/rocket_job/plugins/job/throttle.rb +3 -6
  36. data/lib/rocket_job/plugins/job/worker.rb +2 -2
  37. data/lib/rocket_job/server.rb +14 -3
  38. data/lib/rocket_job/sliced/input.rb +336 -0
  39. data/lib/rocket_job/sliced/output.rb +99 -0
  40. data/lib/rocket_job/sliced/slice.rb +166 -0
  41. data/lib/rocket_job/sliced/slices.rb +166 -0
  42. data/lib/rocket_job/sliced/writer/input.rb +60 -0
  43. data/lib/rocket_job/sliced/writer/output.rb +82 -0
  44. data/lib/rocket_job/version.rb +1 -1
  45. data/lib/rocket_job/worker.rb +2 -2
  46. data/lib/rocketjob.rb +28 -0
  47. metadata +51 -62
  48. data/test/config/database.yml +0 -5
  49. data/test/config/mongoid.yml +0 -88
  50. data/test/config_test.rb +0 -10
  51. data/test/dirmon_entry_test.rb +0 -313
  52. data/test/dirmon_job_test.rb +0 -216
  53. data/test/files/text.txt +0 -3
  54. data/test/job_test.rb +0 -71
  55. data/test/jobs/housekeeping_job_test.rb +0 -102
  56. data/test/jobs/on_demand_job_test.rb +0 -59
  57. data/test/jobs/upload_file_job_test.rb +0 -107
  58. data/test/plugins/cron_test.rb +0 -166
  59. data/test/plugins/job/callbacks_test.rb +0 -166
  60. data/test/plugins/job/defaults_test.rb +0 -53
  61. data/test/plugins/job/logger_test.rb +0 -56
  62. data/test/plugins/job/model_test.rb +0 -94
  63. data/test/plugins/job/persistence_test.rb +0 -94
  64. data/test/plugins/job/state_machine_test.rb +0 -116
  65. data/test/plugins/job/throttle_test.rb +0 -111
  66. data/test/plugins/job/worker_test.rb +0 -199
  67. data/test/plugins/processing_window_test.rb +0 -109
  68. data/test/plugins/restart_test.rb +0 -193
  69. data/test/plugins/retry_test.rb +0 -88
  70. data/test/plugins/singleton_test.rb +0 -92
  71. data/test/plugins/state_machine_event_callbacks_test.rb +0 -102
  72. data/test/plugins/state_machine_test.rb +0 -67
  73. data/test/plugins/transaction_test.rb +0 -84
  74. data/test/test_db.sqlite3 +0 -0
  75. data/test/test_helper.rb +0 -17
@@ -1,313 +0,0 @@
1
- require_relative 'test_helper'
2
-
3
- # Unit Test for RocketJob::Job
4
- class DirmonEntryTest < Minitest::Test
5
- class TestJob < RocketJob::Job
6
- # Dirmon will store the filename in this property when starting the job
7
- field :upload_file_name, type: String
8
-
9
- field :user_id, type: Integer
10
-
11
- def perform
12
- # Do something with the file name stored in :upload_file_name
13
- end
14
- end
15
-
16
- describe RocketJob::DirmonEntry do
17
- let :archive_directory do
18
- '/tmp/archive_directory'
19
- end
20
-
21
- let :archive_path do
22
- archive_path = Pathname.new(archive_directory)
23
- archive_path.mkpath
24
- archive_path.realdirpath
25
- end
26
-
27
- let :dirmon_entry do
28
- dirmon_entry = RocketJob::DirmonEntry.new(
29
- name: 'Test',
30
- job_class_name: 'DirmonEntryTest::TestJob',
31
- pattern: 'test/files/**',
32
- properties: {user_id: 341},
33
- archive_directory: archive_directory
34
- )
35
- dirmon_entry.enable!
36
- assert dirmon_entry.valid?, dirmon_entry.errors.messages.ai
37
- dirmon_entry
38
- end
39
-
40
- before do
41
- RocketJob::Jobs::DirmonJob.delete_all
42
- RocketJob::Jobs::UploadFileJob.delete_all
43
- RocketJob::DirmonEntry.delete_all
44
- end
45
-
46
- describe '.config' do
47
- it 'support multiple databases' do
48
- assert_equal 'rocketjob_test', RocketJob::DirmonEntry.collection.database.name
49
- end
50
- end
51
-
52
- describe '#job_class' do
53
- describe 'with a nil job_class_name' do
54
- it 'return nil' do
55
- entry = RocketJob::DirmonEntry.new
56
- assert_nil entry.job_class
57
- end
58
- end
59
-
60
- describe 'with an unknown job_class_name' do
61
- it 'return nil' do
62
- entry = RocketJob::DirmonEntry.new(job_class_name: 'FakeJobThatDoesNotExistAnyWhereIPromise')
63
- assert_nil entry.job_class
64
- end
65
- end
66
-
67
- describe 'with a valid job_class_name' do
68
- it 'return job class' do
69
- entry = RocketJob::DirmonEntry.new(job_class_name: 'RocketJob::Job')
70
- assert_equal RocketJob::Job, entry.job_class
71
- assert_equal 0, entry.properties.size
72
- end
73
- end
74
- end
75
-
76
- describe '.whitelist_paths' do
77
- it 'default to []' do
78
- assert_equal [], RocketJob::DirmonEntry.whitelist_paths
79
- end
80
- end
81
-
82
- describe '.add_whitelist_path' do
83
- after do
84
- RocketJob::DirmonEntry.whitelist_paths.each { |path| RocketJob::DirmonEntry.delete_whitelist_path(path) }
85
- end
86
-
87
- it 'convert relative path to an absolute one' do
88
- path = Pathname('test/files').realpath.to_s
89
- assert_equal path, RocketJob::DirmonEntry.add_whitelist_path('test/files')
90
- assert_equal [path], RocketJob::DirmonEntry.whitelist_paths
91
- end
92
-
93
- it 'prevent duplicates' do
94
- path = Pathname('test/files').realpath.to_s
95
- assert_equal path, RocketJob::DirmonEntry.add_whitelist_path('test/files')
96
- assert_equal path, RocketJob::DirmonEntry.add_whitelist_path('test/files')
97
- assert_equal path, RocketJob::DirmonEntry.add_whitelist_path(path)
98
- assert_equal [path], RocketJob::DirmonEntry.whitelist_paths
99
- end
100
- end
101
-
102
- describe '#fail!' do
103
- it 'fail with message' do
104
- dirmon_entry.fail!('myworker:2323', 'oh no')
105
- assert dirmon_entry.failed?
106
- assert_equal 'RocketJob::DirmonEntryException', dirmon_entry.exception.class_name
107
- assert_equal 'oh no', dirmon_entry.exception.message
108
- end
109
-
110
- it 'fail with exception' do
111
- exception = nil
112
- begin
113
- blah
114
- rescue Exception => exc
115
- exception = exc
116
- end
117
- dirmon_entry.fail!('myworker:2323', exception)
118
-
119
- assert_equal true, dirmon_entry.failed?
120
- assert_equal exception.class.name.to_s, dirmon_entry.exception.class_name
121
- assert dirmon_entry.exception.message.include?('undefined local variable or method'), dirmon_entry.attributes.inspect
122
- end
123
- end
124
-
125
- describe '#validate' do
126
- it 'strip_whitespace' do
127
- dirmon_entry.pattern = ' test/files/*'
128
- dirmon_entry.archive_directory = ' test/archive/ '
129
- assert dirmon_entry.valid?
130
- assert_equal 'test/files/*', dirmon_entry.pattern
131
- assert_equal 'test/archive/', dirmon_entry.archive_directory
132
- end
133
-
134
- describe 'pattern' do
135
- it 'present' do
136
- dirmon_entry.pattern = nil
137
- refute dirmon_entry.valid?
138
- assert_equal ["can't be blank"], dirmon_entry.errors[:pattern], dirmon_entry.errors.messages.ai
139
- end
140
- end
141
-
142
- describe 'job_class_name' do
143
- it 'ensure presence' do
144
- dirmon_entry.job_class_name = nil
145
- refute dirmon_entry.valid?
146
- assert_equal ["can't be blank"], dirmon_entry.errors[:job_class_name], dirmon_entry.errors.messages.ai
147
- end
148
-
149
- it 'is a RocketJob::Job' do
150
- dirmon_entry.job_class_name = 'String'
151
- refute dirmon_entry.valid?
152
- assert_equal ['Job String must be defined and inherit from RocketJob::Job'], dirmon_entry.errors[:job_class_name], dirmon_entry.errors.messages.ai
153
- end
154
-
155
- it 'is invalid' do
156
- dirmon_entry.job_class_name = 'Blah'
157
- refute dirmon_entry.valid?
158
- assert_equal ['Job Blah must be defined and inherit from RocketJob::Job'], dirmon_entry.errors[:job_class_name], dirmon_entry.errors.messages.ai
159
- end
160
- end
161
-
162
- describe 'properties' do
163
- it 'are valid' do
164
- dirmon_entry.properties = {user_id: 123}
165
- assert dirmon_entry.valid?, dirmon_entry.errors.messages.ai
166
- end
167
-
168
- it 'not valid' do
169
- dirmon_entry.properties = {blah: 123}
170
- refute dirmon_entry.valid?
171
- assert_equal ['Unknown Property: Attempted to set a value for :blah which is not allowed on the job DirmonEntryTest::TestJob'], dirmon_entry.errors[:properties], dirmon_entry.errors.messages.ai
172
- end
173
- end
174
- end
175
-
176
- describe 'with valid entry' do
177
- let :file do
178
- file = Tempfile.new('archive')
179
- File.open(file.path, 'w') { |file| file.write('Hello World') }
180
- file
181
- end
182
-
183
- let :file_name do
184
- file.path
185
- end
186
-
187
- let :pathname do
188
- Pathname.new(file_name)
189
- end
190
-
191
- after do
192
- file.delete
193
- RocketJob::Jobs::DirmonJob.delete_all
194
- end
195
-
196
- describe '#each' do
197
- it 'without archive path' do
198
- dirmon_entry.archive_directory = nil
199
- files = []
200
- dirmon_entry.each do |file_name|
201
- files << file_name
202
- end
203
- assert_nil dirmon_entry.archive_directory
204
- assert_equal 1, files.count
205
- assert_equal Pathname.new('test/files/text.txt').realpath, files.first
206
- end
207
-
208
- it 'with archive path' do
209
- files = []
210
- dirmon_entry.each do |file_name|
211
- files << file_name
212
- end
213
- assert_equal 1, files.count
214
- assert_equal Pathname.new('test/files/text.txt').realpath, files.first
215
- end
216
-
217
- it 'with case-insensitive pattern' do
218
- dirmon_entry.pattern = 'test/files/**/*.TxT'
219
- files = []
220
- dirmon_entry.each do |file_name|
221
- files << file_name
222
- end
223
- assert_equal 1, files.count
224
- assert_equal Pathname.new('test/files/text.txt').realpath, files.first
225
- end
226
-
227
- it 'reads paths inside of the whitelist' do
228
- dirmon_entry.archive_directory = nil
229
- files = []
230
- dirmon_entry.stub(:whitelist_paths, [Pathname.new('test/files').realpath.to_s]) do
231
- dirmon_entry.each do |file_name|
232
- files << file_name
233
- end
234
- end
235
- assert_nil dirmon_entry.archive_directory
236
- assert_equal 1, files.count
237
- assert_equal Pathname.new('test/files/text.txt').realpath, files.first
238
- end
239
-
240
- it 'skips paths outside of the whitelist' do
241
- dirmon_entry.archive_directory = nil
242
- files = []
243
- dirmon_entry.stub(:whitelist_paths, [Pathname.new('test/config').realpath.to_s]) do
244
- dirmon_entry.each do |file_name|
245
- files << file_name
246
- end
247
- end
248
- assert_nil dirmon_entry.archive_directory
249
- assert_equal 0, files.count
250
- end
251
- end
252
-
253
- describe '#later' do
254
- it 'enqueues job' do
255
- job = dirmon_entry.later(pathname)
256
- assert created_job = RocketJob::Jobs::UploadFileJob.last
257
- assert_equal job.id, created_job.id
258
- assert job.queued?
259
- end
260
-
261
- it 'sets attributes' do
262
- job = dirmon_entry.later(pathname)
263
-
264
- upload_file_name = Pathname.new(archive_directory).join("#{job.job_id}_#{File.basename(file_name)}").realdirpath.to_s
265
-
266
- assert_equal dirmon_entry.job_class_name, job.job_class_name
267
- assert_equal dirmon_entry.properties, job.properties
268
- assert_equal upload_file_name, job.upload_file_name
269
- assert_equal "#{dirmon_entry.name}: #{pathname.basename}", job.description
270
- assert_equal pathname.to_s, job.original_file_name
271
- assert job.job_id
272
- end
273
- end
274
-
275
- describe '#archive_file' do
276
- it 'moves file to archive dir' do
277
- job_id = BSON::ObjectId.new
278
- archive_real_name = archive_path.join("#{job_id}_#{File.basename(file_name)}").to_s
279
-
280
- assert File.exist?(file_name)
281
- assert_equal archive_real_name, dirmon_entry.send(:archive_file, job_id, pathname)
282
- refute File.exist?(file_name)
283
- assert File.exist?(archive_real_name)
284
- end
285
- end
286
-
287
- describe '#archive_pathname' do
288
- it 'with fully qualified archive directory' do
289
- assert_equal archive_path.to_s, dirmon_entry.send(:archive_pathname, pathname).to_s
290
- end
291
-
292
- describe 'with relative' do
293
- let :archive_directory do
294
- 'my_archive/files'
295
- end
296
-
297
- it 'archive directory' do
298
- archive_dir = File.join(pathname.realdirpath.dirname, archive_directory)
299
- assert_equal archive_dir, dirmon_entry.send(:archive_pathname, pathname).to_s
300
- end
301
- end
302
-
303
- it 'has a default archive directory' do
304
- e = RocketJob::DirmonEntry.new(
305
- pattern: 'test/files/**/*',
306
- job_class_name: 'RocketJob::Jobs::DirmonJob'
307
- )
308
- assert_equal 'archive', e.archive_directory
309
- end
310
- end
311
- end
312
- end
313
- end
@@ -1,216 +0,0 @@
1
- require_relative 'test_helper'
2
-
3
- # Unit Test for RocketJob::Job
4
- class DirmonJobTest < Minitest::Test
5
- class TestJob < RocketJob::Job
6
- def perform
7
- 3645
8
- end
9
- end
10
-
11
- describe RocketJob::Jobs::DirmonJob do
12
- let :dirmon_job do
13
- RocketJob::Jobs::DirmonJob.new
14
- end
15
-
16
- let :directory do
17
- '/tmp/directory'
18
- end
19
-
20
- let :archive_directory do
21
- '/tmp/archive_directory'
22
- end
23
-
24
- let :dirmon_entry do
25
- RocketJob::DirmonEntry.new(
26
- pattern: "#{directory}/abc/*",
27
- job_class_name: 'DirmonJobTest::TestJob',
28
- properties: {priority: 23},
29
- archive_directory: archive_directory
30
- )
31
- end
32
-
33
- before do
34
- RocketJob::Jobs::DirmonJob.delete_all
35
- FileUtils.makedirs("#{directory}/abc")
36
- end
37
-
38
- after do
39
- FileUtils.remove_dir(archive_directory, true) if Dir.exist?(archive_directory)
40
- FileUtils.remove_dir(directory, true) if Dir.exist?(directory)
41
- end
42
-
43
- describe '#check_file' do
44
- it 'check growing file' do
45
- previous_size = 5
46
- new_size = 10
47
- file = create_temp_file(new_size)
48
- result = dirmon_entry.stub(:later, nil) do
49
- dirmon_job.send(:check_file, dirmon_entry, file, previous_size)
50
- end
51
- assert_equal new_size, result
52
- end
53
-
54
- it 'check completed file' do
55
- previous_size = 10
56
- new_size = 10
57
- file = create_temp_file(new_size)
58
- started = false
59
- result = dirmon_entry.stub(:later, ->(_fn) { started = true }) do
60
- dirmon_job.send(:check_file, dirmon_entry, file, previous_size)
61
- end
62
- assert_nil result
63
- assert started
64
- end
65
-
66
- it 'check deleted file' do
67
- previous_size = 5
68
- file_name = Pathname.new('blah')
69
- assert_raises Errno::ENOENT do
70
- dirmon_job.send(:check_file, dirmon_entry, file_name, previous_size)
71
- end
72
- end
73
- end
74
-
75
- describe '#check_directories' do
76
- before do
77
- RocketJob::DirmonEntry.destroy_all
78
- dirmon_entry.enable!
79
- end
80
-
81
- it 'no files' do
82
- result = dirmon_job.send(:check_directories)
83
- assert_equal 0, result.count
84
- end
85
-
86
- it 'collect new files without enqueuing them' do
87
- create_file("#{directory}/abc/file1", 5)
88
- create_file("#{directory}/abc/file2", 10)
89
-
90
- result = dirmon_job.send(:check_directories)
91
- assert_equal [5, 10], result.values.sort
92
- end
93
-
94
- it 'allow files to grow' do
95
- create_file("#{directory}/abc/file1", 5)
96
- create_file("#{directory}/abc/file2", 10)
97
- dirmon_job.send(:check_directories)
98
- create_file("#{directory}/abc/file1", 10)
99
- create_file("#{directory}/abc/file2", 15)
100
- result = dirmon_job.send(:check_directories)
101
- assert_equal [10, 15], result.values.sort
102
- end
103
-
104
- it 'start all files' do
105
- create_file("#{directory}/abc/file1", 5)
106
- create_file("#{directory}/abc/file2", 10)
107
- files = dirmon_job.send(:check_directories)
108
- assert_equal 2, files.count, files
109
- assert_equal 2, dirmon_job.previous_file_names.count, files
110
-
111
- # files = dirmon_job.send(:check_directories)
112
- # assert_equal 0, files.count, files
113
-
114
- count = 0
115
- result = RocketJob::DirmonEntry.stub_any_instance(:later, ->(_path) { count += 1 }) do
116
- dirmon_job.send(:check_directories)
117
- end
118
- assert_equal 0, result.count, result
119
- assert 2, count
120
- end
121
-
122
- it 'skip files in archive directory' do
123
- dirmon_entry.archive_directory = 'archive'
124
- dirmon_entry.pattern = "#{directory}/abc/**/*"
125
-
126
- file_pathname = Pathname.new("#{directory}/abc/file1")
127
- create_file(file_pathname.to_s, 5)
128
- create_file("#{directory}/abc/file2", 10)
129
-
130
- archive_pathname = dirmon_entry.send(:archive_pathname, file_pathname)
131
- create_file("#{archive_pathname}/file3", 21)
132
-
133
- result = dirmon_job.send(:check_directories)
134
- assert_equal [5, 10], result.values.sort
135
- end
136
- end
137
-
138
- describe '#perform' do
139
- it 'check directories and reschedule' do
140
- previous_file_names = {
141
- "#{directory}/abc/file1" => 5,
142
- "#{directory}/abc/file2" => 10
143
- }
144
- new_file_names = {
145
- "#{directory}/abc/file1" => 10,
146
- "#{directory}/abc/file2" => 10
147
- }
148
- assert_equal 0, RocketJob::Jobs::DirmonJob.count
149
- # perform_now does not save the job, just runs it
150
- dirmon_job = RocketJob::Jobs::DirmonJob.create!(
151
- previous_file_names: previous_file_names,
152
- priority: 11,
153
- check_seconds: 30
154
- )
155
- RocketJob::Jobs::DirmonJob.stub_any_instance(:check_directories, new_file_names) do
156
- dirmon_job.perform_now
157
- end
158
- assert dirmon_job.completed?, dirmon_job.status.inspect
159
- # Job must destroy on complete
160
- assert_equal 0, RocketJob::Jobs::DirmonJob.where(id: dirmon_job.id).count, -> { RocketJob::Jobs::DirmonJob.all.to_a.ai }
161
-
162
- # Must have enqueued another instance to run in the future
163
- assert_equal 1, RocketJob::Jobs::DirmonJob.count
164
- assert new_dirmon_job = RocketJob::Jobs::DirmonJob.last
165
- refute_equal dirmon_job.id.to_s, new_dirmon_job.id.to_s
166
- assert new_dirmon_job.run_at
167
- assert_equal 11, new_dirmon_job.priority
168
- assert_equal 30, new_dirmon_job.check_seconds
169
- assert new_dirmon_job.queued?
170
-
171
- new_dirmon_job.destroy
172
- end
173
-
174
- it 'check directories and reschedule even on exception' do
175
- RocketJob::Jobs::DirmonJob.destroy_all
176
- # perform_now does not save the job, just runs it
177
- dirmon_job = RocketJob::Jobs::DirmonJob.create!(
178
- priority: 11,
179
- check_seconds: 30,
180
- destroy_on_complete: false
181
- )
182
- RocketJob::Jobs::DirmonJob.stub_any_instance(:check_directories, -> { raise 'Oh no' }) do
183
- assert_raises RuntimeError do
184
- dirmon_job.perform_now
185
- end
186
- end
187
- dirmon_job.save!
188
- assert dirmon_job.aborted?, dirmon_job.status.ai
189
- assert_equal 'RuntimeError', dirmon_job.exception.class_name, dirmon_job.exception.attributes
190
- assert_equal 'Oh no', dirmon_job.exception.message, dirmon_job.exception.attributes
191
-
192
- # Must have enqueued another instance to run in the future
193
- assert_equal 2, RocketJob::Jobs::DirmonJob.count, -> { RocketJob::Jobs::DirmonJob.all.ai }
194
- assert new_dirmon_job = RocketJob::Jobs::DirmonJob.queued.first
195
- assert new_dirmon_job.run_at
196
- assert_equal 11, new_dirmon_job.priority, -> { new_dirmon_job.attributes.ai }
197
- assert_equal 30, new_dirmon_job.check_seconds
198
- assert new_dirmon_job.queued?, new_dirmon_job.state
199
-
200
- new_dirmon_job.destroy
201
- end
202
- end
203
-
204
- def create_file(file_name, size)
205
- File.open(file_name, 'wb') { |file| file.write('*' * size) }
206
- end
207
-
208
- def create_temp_file(size)
209
- file = Tempfile.new('check_file')
210
- file_name = file.path
211
- File.open(file_name, 'wb') { |f| f.write('*' * size) }
212
- assert_equal size, File.size(file_name)
213
- file
214
- end
215
- end
216
- end