shrine-gridfs 0.3.1 → 0.3.2
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 +4 -4
- data/README.md +9 -0
- data/lib/shrine/storage/gridfs.rb +79 -45
- data/shrine-gridfs.gemspec +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 32f189d0c100716ffe7658f1bf04e84f6ed05415
|
4
|
+
data.tar.gz: 2ede8fa5db17c83fff263cd33e7d1434cad9da96
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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 =
|
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
|
-
!!
|
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
|
-
|
112
|
-
bucket.chunks_collection
|
146
|
+
file
|
113
147
|
end
|
114
148
|
|
115
149
|
def bson_id(id)
|
data/shrine-gridfs.gemspec
CHANGED