shrine-gridfs 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b919da6ec801c8888bf1fbeb877cbdc8ad251d43
4
- data.tar.gz: a3cbea2effb35eaee531176df0bcd533749bae62
3
+ metadata.gz: 32f189d0c100716ffe7658f1bf04e84f6ed05415
4
+ data.tar.gz: 2ede8fa5db17c83fff263cd33e7d1434cad9da96
5
5
  SHA512:
6
- metadata.gz: cf9beeb12753001aaf4366ecc0507ea450accd740994b9d28d9c31f4e94dba1c02f71668ebeb946692e5b29ad76feedb38b72ad53443c687fc5c1d87d24f569a
7
- data.tar.gz: f668ac2435e9e46dc46b2e28eaa2fe37aa30cf80a716331901096f0175e71455e3b4773f6a74369c176a88c079ba3969f3e7c575bdde00bc8a617cf2989d7933
6
+ metadata.gz: e0cd1b8dfbfaaf44644777f45b087b49485dd19528c4a2b1eff61a0fb1e932b891f7e4be4150cc134deea9940045fb4784ed1ca08e13c3ebb437bf28b0378384
7
+ data.tar.gz: b8394324dea43b926e78ae961cfaecb949d98983c5afde5a0c0752c8074fd5b1ea3c70be7a6058c44f035cd3cef801af8a0e14aa003a750ab8af75bf17acbb20
data/README.md CHANGED
@@ -40,6 +40,15 @@ change that via `:chunk_size`:
40
40
  Shrine::Storage::Gridfs.new(client: client, chunk_size: 1*1024*1024) # 1MB
41
41
  ```
42
42
 
43
+ ### Batch size
44
+
45
+ When Gridfs storage uploads or copies a file, it will ensure that no more
46
+ than `:batch_size` of data is loaded into memory at once (defaults to 5MB).
47
+
48
+ ```rb
49
+ Shrine::Storage::Gridfs.new(client: client, batch_size: 10*1024*1024) # 10MB
50
+ ```
51
+
43
52
  ### URLs
44
53
 
45
54
  You can generate URLs through which the GridFS files will be streamed with the
@@ -8,53 +8,26 @@ class Shrine
8
8
  class Gridfs
9
9
  attr_reader :client, :prefix, :bucket, :chunk_size
10
10
 
11
- BATCH_SIZE = 5 * 1024 * 1024
12
-
13
- def initialize(client:, prefix: "fs", chunk_size: 256*1024, **options)
11
+ def initialize(client:, prefix: "fs", chunk_size: 256*1024, batch_size: 5 * 1024*1024, **options)
14
12
  @client = client
15
13
  @prefix = prefix
16
14
  @chunk_size = chunk_size
15
+ @batch_size = batch_size
17
16
  @bucket = @client.database.fs(bucket_name: @prefix)
18
17
 
19
18
  @bucket.send(:ensure_indexes!)
20
19
  end
21
20
 
22
21
  def upload(io, id, shrine_metadata: {}, **)
23
- file = create_file(id, shrine_metadata: shrine_metadata)
24
-
25
- until io.eof?
26
- chunk = io.read([BATCH_SIZE, chunk_size].max, buffer ||= "")
27
- grid_chunks = Mongo::Grid::File::Chunk.split(chunk, file.info, offset ||= 0)
28
-
29
- chunks_collection.insert_many(grid_chunks)
30
-
31
- offset += grid_chunks.count
32
- grid_chunks.each { |grid_chunk| grid_chunk.data.data.clear } # deallocate strings
33
- chunk.clear # deallocate string
22
+ if copyable?(io, id)
23
+ copy(io, id, shrine_metadata: shrine_metadata)
24
+ else
25
+ create(io, id, shrine_metadata: shrine_metadata)
34
26
  end
35
-
36
- files_collection.find(_id: file.id).update_one(
37
- "$set" => {
38
- length: io.size,
39
- uploadDate: Time.now.utc,
40
- md5: file.info.md5.hexdigest,
41
- }
42
- )
43
- end
44
-
45
- def move(io, id, shrine_metadata: {}, **)
46
- file = create_file(id, shrine_metadata: shrine_metadata)
47
-
48
- chunks_collection.find(files_id: bson_id(io.id)).update_many("$set" => {files_id: file.id})
49
- files_collection.delete_one(_id: bson_id(io.id))
50
- end
51
-
52
- def movable?(io, id)
53
- io.is_a?(UploadedFile) && io.storage.is_a?(Storage::Gridfs)
54
27
  end
55
28
 
56
29
  def open(id)
57
- content_length = bucket.find(_id: bson_id(id)).limit(1).first[:length]
30
+ content_length = file_info(id)[:length]
58
31
  stream = bucket.open_download_stream(bson_id(id))
59
32
 
60
33
  Down::ChunkedIO.new(
@@ -65,7 +38,7 @@ class Shrine
65
38
  end
66
39
 
67
40
  def exists?(id)
68
- !!bucket.find(_id: bson_id(id)).first
41
+ !!file_info(id)
69
42
  end
70
43
 
71
44
  def delete(id)
@@ -87,29 +60,90 @@ class Shrine
87
60
  chunks_collection.find.delete_many
88
61
  end
89
62
 
63
+ protected
64
+
65
+ def file_info(id)
66
+ bucket.find(_id: bson_id(id)).limit(1).first
67
+ end
68
+
69
+ def files_collection
70
+ bucket.files_collection
71
+ end
72
+
73
+ def chunks_collection
74
+ bucket.chunks_collection
75
+ end
76
+
90
77
  private
91
78
 
79
+ def create(io, id, shrine_metadata: {})
80
+ file = create_file(id, shrine_metadata: shrine_metadata)
81
+
82
+ until io.eof?
83
+ chunk = io.read([@batch_size, chunk_size].max, buffer ||= "")
84
+ grid_chunks = Mongo::Grid::File::Chunk.split(chunk, file.info, offset ||= 0)
85
+
86
+ chunks_collection.insert_many(grid_chunks)
87
+
88
+ offset += grid_chunks.count
89
+ grid_chunks.each { |grid_chunk| grid_chunk.data.data.clear } # deallocate strings
90
+ chunk.clear # deallocate string
91
+ end
92
+
93
+ files_collection.find(_id: file.id).update_one("$set" => {
94
+ length: io.size,
95
+ uploadDate: Time.now.utc,
96
+ md5: file.info.md5.hexdigest,
97
+ })
98
+ end
99
+
100
+ def copy(io, id, shrine_metadata: {})
101
+ source_storage = io.storage
102
+ source_info = source_storage.file_info(io.id)
103
+ dest_info = source_info.merge(_id: BSON::ObjectId.new)
104
+
105
+ batch_size = (@batch_size.to_f / chunk_size).ceil
106
+ chunk_batches = source_storage.chunks_collection
107
+ .find(files_id: source_info[:_id])
108
+ .batch_size(batch_size).each_slice(batch_size)
109
+
110
+ chunk_batches.each do |chunks|
111
+ chunks.each do |chunk|
112
+ chunk[:_id] = BSON::ObjectId.new
113
+ chunk[:files_id] = dest_info[:_id]
114
+ end
115
+
116
+ chunks_collection.insert_many(chunks)
117
+
118
+ chunks.each do |chunk|
119
+ chunk[:data].data.clear # deallocate strings
120
+ end
121
+ end
122
+
123
+ dest_info[:uploadDate] = Time.now.utc
124
+ dest_info[:filename] = shrine_metadata["filename"] || id
125
+ files_collection.insert_one(dest_info)
126
+ id.replace(dest_info[:_id].to_s + File.extname(id))
127
+ end
128
+
129
+ def copyable?(io, id)
130
+ io.is_a?(UploadedFile) && io.storage.is_a?(Storage::Gridfs)
131
+ end
132
+
92
133
  def create_file(id, shrine_metadata: {})
93
134
  file = Mongo::Grid::File.new("",
94
135
  filename: shrine_metadata["filename"] || id,
95
- content_type: shrine_metadata["mime_type"],
136
+ content_type: shrine_metadata["mime_type"] || "application/octet-stream",
96
137
  metadata: shrine_metadata,
97
138
  chunk_size: chunk_size,
98
139
  )
99
- id.replace(file.id.to_s + File.extname(id))
100
140
 
101
141
  bucket.insert_one(file)
102
142
 
143
+ id.replace(file.id.to_s + File.extname(id))
103
144
  file.info.document[:md5] = Digest::MD5.new
104
- file
105
- end
106
-
107
- def files_collection
108
- bucket.files_collection
109
- end
110
145
 
111
- def chunks_collection
112
- bucket.chunks_collection
146
+ file
113
147
  end
114
148
 
115
149
  def bson_id(id)
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |gem|
2
2
  gem.name = "shrine-gridfs"
3
- gem.version = "0.3.1"
3
+ gem.version = "0.3.2"
4
4
 
5
5
  gem.required_ruby_version = ">= 2.1"
6
6
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shrine-gridfs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Janko Marohnić