kithe 2.0.0.pre.alpha2 → 2.0.0.pre.beta1
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/app/jobs/kithe/create_derivatives_job.rb +2 -2
- data/app/models/kithe/asset.rb +82 -154
- data/app/models/kithe/asset/derivative_creator.rb +32 -62
- data/app/models/kithe/asset/derivative_definition.rb +12 -13
- data/app/models/kithe/asset/set_shrine_uploader.rb +64 -0
- data/app/models/kithe/collection.rb +0 -6
- data/app/models/kithe/model.rb +0 -21
- data/app/models/kithe/work.rb +0 -5
- data/app/uploaders/kithe/asset_uploader.rb +15 -78
- data/lib/kithe/version.rb +4 -1
- data/lib/shrine/plugins/kithe_checksum_signatures.rb +41 -0
- data/lib/shrine/plugins/kithe_controllable_backgrounding.rb +53 -0
- data/lib/shrine/plugins/kithe_derivative_definitions.rb +101 -0
- data/lib/shrine/plugins/kithe_derivatives.rb +54 -0
- data/lib/shrine/plugins/kithe_determine_mime_type.rb +39 -0
- data/lib/shrine/plugins/kithe_persisted_derivatives.rb +161 -0
- data/lib/shrine/plugins/kithe_promotion_callbacks.rb +4 -0
- data/lib/shrine/plugins/kithe_promotion_directives.rb +33 -3
- data/lib/shrine/plugins/kithe_storage_location.rb +53 -4
- data/lib/tasks/kithe_tasks.rake +22 -15
- data/spec/dummy/log/development.log +867 -0
- data/spec/dummy/log/test.log +26005 -0
- data/spec/models/kithe/asset/asset_derivatives_spec.rb +137 -0
- data/spec/models/kithe/asset/asset_promotion_hooks_spec.rb +26 -5
- data/spec/models/kithe/asset/set_shrine_uploader_spec.rb +39 -0
- data/spec/models/kithe/asset_spec.rb +9 -59
- data/spec/models/kithe/model_spec.rb +0 -32
- data/spec/shrine/kithe_accept_remote_url_spec.rb +49 -0
- data/spec/shrine/kithe_checksum_signatures_spec.rb +63 -0
- data/spec/shrine/kithe_derivative_definitions_spec.rb +303 -0
- data/spec/shrine/kithe_persisted_derivatives_spec.rb +424 -0
- data/spec/shrine/kithe_storage_location_spec.rb +43 -15
- data/spec/spec_helper.rb +7 -6
- data/spec/test_support/images/3x3_pixel.jpg +0 -0
- data/spec/test_support/shrine_spec_support.rb +2 -1
- metadata +23 -23
- data/app/models/kithe/asset/derivative_updater.rb +0 -119
- data/app/models/kithe/derivative.rb +0 -15
- data/app/uploaders/kithe/derivative_uploader.rb +0 -48
- data/spec/models/kithe/asset/asset_create_derivatives_spec.rb +0 -320
- data/spec/models/kithe/derivative_spec.rb +0 -168
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cfaa6ce3c41abdc0779014cb028d3ae7acbbfee6124eb24abca06f52e6f60c30
|
4
|
+
data.tar.gz: 4f3951e52b4175c86933870933fd38c0c84dfcf11a5ad8cd18f1eb8c479305b0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6fe1836bde7b33a29d95324afe745ceeecb59ca95c8952775cce39dd8233c8daf171da971cc4a7bb2691e8dad2b91d50766c9232e3dce5b333da6f14d2f8d6bd
|
7
|
+
data.tar.gz: de9bcd5fc0c22c18d9dde7ea9ec1bdc708e08035ee0f5d208131628d6d37bbc61574ae213b0ef69e6161c1fbdf334aad545c734614e10cee8f63f96666ed86dc
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Kithe
|
2
2
|
class CreateDerivativesJob < Job
|
3
|
-
def perform(asset
|
4
|
-
asset.create_derivatives
|
3
|
+
def perform(asset)
|
4
|
+
asset.create_derivatives
|
5
5
|
end
|
6
6
|
# This error typically occurs when several large assets, whose derivatives
|
7
7
|
# take a long time to generate, are deleted immediately after ingest.
|
data/app/models/kithe/asset.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
class Kithe::Asset < Kithe::Model
|
2
|
-
|
2
|
+
include Kithe::Asset::SetShrineUploader
|
3
3
|
|
4
4
|
# These associations exist for hetereogenous eager-loading, but hide em.
|
5
5
|
# They are defined as self-pointing below.
|
@@ -26,15 +26,12 @@ class Kithe::Asset < Kithe::Model
|
|
26
26
|
:md5, :sha1, :sha512,
|
27
27
|
to: :file, allow_nil: true
|
28
28
|
delegate :stored?, to: :file_attacher
|
29
|
-
delegate :set_promotion_directives, to: :file_attacher
|
29
|
+
delegate :set_promotion_directives, :promotion_directives, to: :file_attacher
|
30
30
|
|
31
|
-
after_save :remove_invalid_derivatives
|
32
31
|
|
33
|
-
# will be sent to file_attacher.
|
32
|
+
# will be sent to file_attacher.set_promotion_directives, provided by our
|
34
33
|
# kithe_promotion_hooks shrine plugin.
|
35
|
-
class_attribute :promotion_directives,
|
36
|
-
|
37
|
-
class_attribute :derivative_definitions, instance_writer: false, default: []
|
34
|
+
class_attribute :promotion_directives, instance_accessor: false, default: {}
|
38
35
|
|
39
36
|
# Callbacks are called by our kiteh_promotion_callbacks shrine plugin, around
|
40
37
|
# shrine promotion. A before callback can cancel promotion with the usual
|
@@ -45,112 +42,94 @@ class Kithe::Asset < Kithe::Model
|
|
45
42
|
before_promotion :refresh_metadata_before_promotion
|
46
43
|
after_promotion :schedule_derivatives
|
47
44
|
|
48
|
-
|
49
|
-
|
50
|
-
#
|
51
|
-
# when #create_derivatives is called, for instance automatically after promotion.
|
45
|
+
# A convenience to call file_attacher.create_persisted_derivatives (from :kithe_derivatives)
|
46
|
+
# to create derivatives with conncurrent access safety, with the :kithe_derivatives
|
47
|
+
# processor argument, to create derivatives defined using kithe_derivative_definitions.
|
52
48
|
#
|
53
|
-
#
|
54
|
-
#
|
55
|
-
# (shrine-compatible) IO-like object. It will usually be done inside a custom Asset
|
56
|
-
# class definition.
|
49
|
+
# This is designed for use with kithe_derivatives processor, and has options only relevant
|
50
|
+
# to it, although could be expanded to take a processor argument in the future if needed.
|
57
51
|
#
|
58
|
-
#
|
59
|
-
#
|
60
|
-
#
|
61
|
-
# end
|
52
|
+
# Create derivatives for every definition added to uploader/attacher with kithe_derivatives
|
53
|
+
# `define_derivative`. Ordinarily will create a definition for every definition
|
54
|
+
# that has not been marked `default_create: false`.
|
62
55
|
#
|
63
|
-
#
|
64
|
-
#
|
56
|
+
# But you can also pass `only` and/or `except` to customize the list of definitions to be created,
|
57
|
+
# possibly including some that are `default_create: false`.
|
65
58
|
#
|
66
|
-
#
|
67
|
-
#
|
68
|
-
# have to make any intermediate files, you are responsible for cleaning them up. Ruby stdlib
|
69
|
-
# Tempfile and Dir.mktmpdir may be useful.
|
59
|
+
# create_derivatives should be idempotent. If it has failed having only created some derivatives,
|
60
|
+
# you can always just run it again.
|
70
61
|
#
|
71
|
-
#
|
72
|
-
#
|
62
|
+
# Will normally re-create derivatives (per existing definitions) even if they already exist,
|
63
|
+
# but pass `lazy: false` to skip creating if a derivative with a given key already exists.
|
64
|
+
# This will use the asset `derivatives` association, so if you are doing this in bulk for several
|
65
|
+
# assets, you should eager-load the derivatives association for efficiency.
|
73
66
|
#
|
74
|
-
#
|
75
|
-
# record.width, record.height, record.content_type # etc
|
76
|
-
# end
|
67
|
+
# ## Avoiding eager-download
|
77
68
|
#
|
78
|
-
#
|
79
|
-
#
|
80
|
-
#
|
81
|
-
#
|
82
|
-
#
|
69
|
+
# Additionally, this has a feature to 'trick' shrine into not eager downloading
|
70
|
+
# the original before our kithe_derivatives processor has a chance to decide if it
|
71
|
+
# needs to create any derivatives (based on `lazy` arg), making no-op
|
72
|
+
# create_derivatives so much faster and more efficient, which matters when doing
|
73
|
+
# bulk operations say with our rake task.
|
83
74
|
#
|
84
|
-
#
|
75
|
+
# kithe_derivatives processor must then do a Shrine.with_file to make sure
|
76
|
+
# it's a local file, when needed.
|
85
77
|
#
|
86
|
-
#
|
87
|
-
# included in a no-arg `asset.create_derivatives` that is normally triggered on asset creation.
|
78
|
+
# See https://github.com/shrinerb/shrine/issues/470
|
88
79
|
#
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
# the most specific one will be used. That is, for a JPG, `image/jpeg` beats `image` beats no restriction.
|
93
|
-
def self.define_derivative(key, storage_key: :kithe_derivatives, content_type: nil, default_create: true, &block)
|
94
|
-
# Make sure we dup the array to handle sub-classes on class_attribute
|
95
|
-
self.derivative_definitions = self.derivative_definitions.dup.push(
|
96
|
-
DerivativeDefinition.new(
|
97
|
-
key: key,
|
98
|
-
storage_key: storage_key,
|
99
|
-
content_type: content_type,
|
100
|
-
default_create: default_create,
|
101
|
-
proc: block
|
102
|
-
)
|
103
|
-
)
|
104
|
-
end
|
80
|
+
def create_derivatives(only: nil, except: nil, lazy: false)
|
81
|
+
source = file
|
82
|
+
return false unless source
|
105
83
|
|
106
|
-
|
107
|
-
|
108
|
-
self.derivative_definitions.collect(&:key).uniq.collect(&:to_s)
|
109
|
-
end
|
84
|
+
#local_files = file_attacher.process_derivatives(:kithe_derivatives, only: only, except: except, lazy: lazy)
|
85
|
+
local_files = _process_kithe_derivatives_without_download(source, only: only, except: except, lazy: lazy)
|
110
86
|
|
111
|
-
|
112
|
-
# remove them -- only by key, will remove any definitions with that key regardless
|
113
|
-
# of content_type restrictions.
|
114
|
-
#
|
115
|
-
# This could be considered rather bad OO design, you might want to consider
|
116
|
-
# a different class hieararchy where you don't have to do this. But it's here.
|
117
|
-
def self.remove_derivative_definition!(*keys)
|
118
|
-
keys = keys.collect(&:to_sym)
|
119
|
-
self.derivative_definitions = self.derivative_definitions.reject do |defn|
|
120
|
-
keys.include?(defn.key.to_sym)
|
121
|
-
end
|
87
|
+
file_attacher.add_persisted_derivatives(local_files)
|
122
88
|
end
|
123
89
|
|
124
|
-
#
|
125
|
-
#
|
90
|
+
# Working around Shrine's insistence on pre-downloading original before calling derivative processor.
|
91
|
+
# We want to avoid that, so when our `lazy` argument is in use, original does not get eagerly downloaded,
|
92
|
+
# but only gets downloaded if needed to make derivatives.
|
126
93
|
#
|
127
|
-
#
|
128
|
-
#
|
94
|
+
# This is a somewhat hacky way to do that, loking at the internals of shrine `process_derivatives`,
|
95
|
+
# and pulling them out to skip the parts we don't want. We also lose shrine instrumentation
|
96
|
+
# around this action.
|
129
97
|
#
|
130
|
-
#
|
131
|
-
# you can always just run it again.
|
98
|
+
# See: https://github.com/shrinerb/shrine/issues/470
|
132
99
|
#
|
133
|
-
#
|
134
|
-
#
|
135
|
-
#
|
136
|
-
#
|
137
|
-
|
138
|
-
|
100
|
+
# If that were resolved, the 'ordinary' shrine thing would be to replace calls
|
101
|
+
# to this local private method with:
|
102
|
+
#
|
103
|
+
# file_attacher.process_derivatives(:kithe_derivatives, only: only, except: except, lazy: lazy)
|
104
|
+
#
|
105
|
+
private def _process_kithe_derivatives_without_download(source, **options)
|
106
|
+
processor = file_attacher.class.derivatives_processor(:kithe_derivatives)
|
107
|
+
local_files = file_attacher.instance_exec(source, **options, &processor)
|
139
108
|
end
|
140
109
|
|
141
|
-
#
|
110
|
+
# Just a convennience for file_attacher.add_persisted_derivatives (from :kithe_derivatives),
|
111
|
+
# feel free to use that if you want to add more than one etc. By default stores to
|
112
|
+
# :kithe_derivatives, just as `add_persisted_derivatives` does.
|
113
|
+
#
|
114
|
+
# Note that just like shrine's own usual `add_derivative(s)`, it assumes any files
|
115
|
+
# you pass it are meant to be temporary and will delete them, unless you pass
|
116
|
+
# `delete: false`.
|
117
|
+
#
|
118
|
+
# Adds an associated derivative with key and io bytestream specified,
|
119
|
+
# doing so in a way that is safe from race conditions under multi-process
|
120
|
+
# concurrency.
|
121
|
+
#
|
142
122
|
# Normally you don't use this with derivatives defined with `define_derivative`,
|
143
123
|
# this is used by higher-level API. But if you'd like to add a derivative not defined
|
144
124
|
# with `define_derivative`, or for any other reason would like to manually add
|
145
|
-
# a derivative
|
125
|
+
# a derivative.
|
146
126
|
#
|
147
|
-
#
|
148
|
-
#
|
149
|
-
# and if the asset#file is changed to a different bytestream (compared to what's in memory
|
150
|
-
# for this asset), we don't end up saving a derivative based on old one.
|
127
|
+
# Can specify any options normally allowed for kithe `add_persisted_derivatives`,
|
128
|
+
# which are also generally any allowed for shrine `add_derivative`.
|
151
129
|
#
|
152
|
-
#
|
153
|
-
#
|
130
|
+
# asset.update_derivative("big_thumb", File.open(something))
|
131
|
+
# asset.update_derivative("something", File.open(something), delete: false)
|
132
|
+
# asset.update_derivative("something", File.open(something), storage_key: :registered_storage, metadata: { "foo": "bar" })
|
154
133
|
#
|
155
134
|
# @param key derivative-type identifying key
|
156
135
|
# @param io An IO-like object (according to Shrine), bytestream for the derivative
|
@@ -158,30 +137,20 @@ class Kithe::Asset < Kithe::Model
|
|
158
137
|
# @param metadata an optional hash of key/values to set as default metadata for the Derivative#file
|
159
138
|
# shrine object.
|
160
139
|
#
|
161
|
-
# @return [
|
140
|
+
# @return [Shrine::UploadedFile] the Derivative created, or false if it was not created because no longer
|
162
141
|
# applicable (underlying Asset#file has changed in db)
|
163
|
-
def update_derivative(key, io,
|
164
|
-
|
165
|
-
|
166
|
-
end
|
142
|
+
def update_derivative(key, io, **options)
|
143
|
+
result = update_derivatives({ key => io }, **options)
|
144
|
+
result && result.values.first
|
167
145
|
end
|
168
146
|
|
169
|
-
def
|
170
|
-
|
171
|
-
derivatives.find_all { |d| d.key == key.to_s }.each do |deriv|
|
172
|
-
derivatives.delete(deriv)
|
173
|
-
end
|
174
|
-
else
|
175
|
-
Kithe::Derivative.where(key: key.to_s, asset: self).each do |deriv|
|
176
|
-
deriv.destroy!
|
177
|
-
end
|
178
|
-
end
|
147
|
+
def update_derivatives(deriv_hash, **options)
|
148
|
+
file_attacher.add_persisted_derivatives(deriv_hash, **options)
|
179
149
|
end
|
180
150
|
|
181
|
-
#
|
182
|
-
|
183
|
-
|
184
|
-
derivatives.find {|d| d.key == key.to_s }
|
151
|
+
# just a convenience for kithe remove_persisted_derivatives
|
152
|
+
def remove_derivatives(*keys)
|
153
|
+
file_attacher.remove_persisted_derivatives(*keys)
|
185
154
|
end
|
186
155
|
|
187
156
|
# Runs the shrine promotion step, that we normally have in backgrounding, manually
|
@@ -205,41 +174,6 @@ class Kithe::Asset < Kithe::Model
|
|
205
174
|
file_attacher.atomic_promote(**context)
|
206
175
|
end
|
207
176
|
|
208
|
-
# The derivative creator sets metadata when it's created all derivatives
|
209
|
-
# defined as `default_create`. So we can tell you if it's done or not.
|
210
|
-
def derivatives_created?
|
211
|
-
if file
|
212
|
-
!!file.metadata["derivatives_created"]
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
# Take out a DB lock on the asset with unchanged sha512 saved in metadata. If a lock
|
217
|
-
# can't be acquired -- which would be expected to be because the asset has already changed
|
218
|
-
# and has a new sha for some reason -- returns nil.
|
219
|
-
#
|
220
|
-
# Useful for making a change to an asset making sure it applies to a certain original file.
|
221
|
-
#
|
222
|
-
# Needs to be done in a transaction, and you should keep the transaction SMALL AS POSSIBLE.
|
223
|
-
# We can't check to make sure you're in a transaction reliably because of Rails transactional
|
224
|
-
# tests, you gotta do it!
|
225
|
-
#
|
226
|
-
# This method is mostly intended for internal Kithe use, cause it's a bit tricky.
|
227
|
-
def acquire_lock_on_sha
|
228
|
-
raise ArgumentError.new("Can't acquire lock without sha512 in metadata") if self.sha512.blank?
|
229
|
-
|
230
|
-
Kithe::Asset.where(id: self.id).where("file_data -> 'metadata' ->> 'sha512' = ?", self.sha512).lock.first
|
231
|
-
end
|
232
|
-
|
233
|
-
# Intentionally only true if there WAS a sha512 before AND it's changed.
|
234
|
-
# Allowing false on nil previous sha512 allows certain conditions, mostly only
|
235
|
-
# in testing, where you want to assign a derivative to not-yet-promoted file.
|
236
|
-
def saved_change_to_file_sha?
|
237
|
-
saved_change_to_file_data? &&
|
238
|
-
saved_change_to_file_data.first.try(:dig, "metadata", "sha512") != nil &&
|
239
|
-
saved_change_to_file_data.first.try(:dig, "metadata", "sha512") !=
|
240
|
-
saved_change_to_file_data.second.try(:dig, "metadata", "sha512")
|
241
|
-
end
|
242
|
-
|
243
177
|
# An Asset is it's own representative
|
244
178
|
def representative
|
245
179
|
self
|
@@ -252,8 +186,10 @@ class Kithe::Asset < Kithe::Model
|
|
252
186
|
|
253
187
|
def initialize(*args)
|
254
188
|
super
|
255
|
-
|
256
|
-
|
189
|
+
|
190
|
+
# copy class-level global promotion directives as initial instance value
|
191
|
+
if self.class.promotion_directives.present?
|
192
|
+
self.set_promotion_directives(self.class.promotion_directives)
|
257
193
|
end
|
258
194
|
end
|
259
195
|
|
@@ -261,7 +197,7 @@ class Kithe::Asset < Kithe::Model
|
|
261
197
|
|
262
198
|
# called by after_promotion hook
|
263
199
|
def schedule_derivatives
|
264
|
-
return unless self.
|
200
|
+
return unless self.file_attacher.kithe_derivative_definitions.present? # no need to schedule if we don't have any
|
265
201
|
|
266
202
|
Kithe::TimingPromotionDirective.new(key: :create_derivatives, directives: file_attacher.promotion_directives) do |directive|
|
267
203
|
if directive.inline?
|
@@ -276,12 +212,4 @@ class Kithe::Asset < Kithe::Model
|
|
276
212
|
def refresh_metadata_before_promotion
|
277
213
|
file.refresh_metadata!(promoting: true)
|
278
214
|
end
|
279
|
-
|
280
|
-
# Meant to be called in after_save hook, looks at activerecord dirty tracking in order
|
281
|
-
# to removes all derivatives if the asset sha512 has changed
|
282
|
-
def remove_invalid_derivatives
|
283
|
-
if saved_change_to_file_sha?
|
284
|
-
derivatives.destroy_all
|
285
|
-
end
|
286
|
-
end
|
287
215
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Creates derivatives from definitions stored on an Asset class
|
2
2
|
class Kithe::Asset::DerivativeCreator
|
3
|
-
attr_reader :definitions, :
|
3
|
+
attr_reader :definitions, :shrine_attacher, :only, :except, :lazy, :source_io
|
4
4
|
|
5
5
|
# A helper class that provides the implementation for Kithe::Asset#create_derivatives,
|
6
6
|
# normally only expected to be called from there.
|
@@ -13,57 +13,62 @@ class Kithe::Asset::DerivativeCreator
|
|
13
13
|
# (deleted) if it is a File or Tempfile object.
|
14
14
|
#
|
15
15
|
# @param definitions an array of DerivativeDefinition
|
16
|
-
# @param
|
16
|
+
# @param shrine_attacher a shrine attacher instance holding attachment state from an individual
|
17
|
+
# model, from eg `asset.file_attacher`
|
17
18
|
# @param only array of definition keys, only execute these (doesn't matter if they are `default_create` or not)
|
18
19
|
# @param except array of definition keys, exclude these from definitions of derivs to be created
|
19
20
|
# @param lazy (default false), Normally we will create derivatives for all applicable definitions,
|
20
21
|
# overwriting any that already exist for a given key. If the definition has changed, a new
|
21
22
|
# derivative created with new definition will overwrite existing. However, if you pass lazy false,
|
22
23
|
# it'll skip derivative creation if the derivative already exists, which can save time
|
23
|
-
# if you are only intending to create missing derivatives.
|
24
|
-
|
25
|
-
# to be calling on multiple assets.
|
26
|
-
# @param mark_created [Boolean] if true will set shrine metadata indicating we've done
|
27
|
-
# derivative creation phase, so Asset#derivatives_created? will return true. Defaults to nil,
|
28
|
-
# meaning true if and only if `only` is nil -- mark created if creating default derivatives.
|
29
|
-
def initialize(definitions, asset, only:nil, except:nil, lazy: false, mark_created: :not_set)
|
24
|
+
# if you are only intending to create missing derivatives.
|
25
|
+
def initialize(definitions, source_io:, shrine_attacher:, only:nil, except:nil, lazy: false)
|
30
26
|
@definitions = definitions
|
31
|
-
@
|
32
|
-
@
|
33
|
-
@
|
27
|
+
@source_io = source_io
|
28
|
+
@shrine_attacher = shrine_attacher
|
29
|
+
@only = only && Array(only).collect(&:to_sym)
|
30
|
+
@except = except && Array(except).collect(&:to_sym)
|
34
31
|
@lazy = !!lazy
|
35
|
-
|
32
|
+
|
33
|
+
unless shrine_attacher.kind_of?(Shrine::Attacher)
|
34
|
+
raise ArgumentError.new("expect second arg Shrine::Attacher not #{shrine_attacher.class}")
|
35
|
+
end
|
36
36
|
end
|
37
37
|
|
38
38
|
def call
|
39
|
-
return unless
|
39
|
+
return unless shrine_attacher.file.present? # if no file, can't create derivatives
|
40
40
|
|
41
41
|
definitions_to_create = applicable_definitions
|
42
|
+
|
42
43
|
if lazy
|
43
|
-
existing_derivative_keys =
|
44
|
+
existing_derivative_keys = shrine_attacher.derivatives.keys
|
44
45
|
definitions_to_create.reject! do |defn|
|
45
|
-
existing_derivative_keys.include?(defn.key
|
46
|
+
existing_derivative_keys.include?(defn.key)
|
46
47
|
end
|
47
48
|
end
|
48
49
|
|
49
|
-
return unless definitions_to_create.present?
|
50
|
+
return {} unless definitions_to_create.present?
|
51
|
+
|
52
|
+
derivatives = {}
|
50
53
|
|
51
|
-
#
|
52
|
-
#
|
53
|
-
#
|
54
|
-
|
54
|
+
# Make sure we have this as a local file, because many processors
|
55
|
+
# require it, for instance for shelling out to command line.
|
56
|
+
# This might trigger a download, but note we are only doing it if we have
|
57
|
+
# `definitions_to_create`, otherwise we already returned.
|
58
|
+
shrine_attacher.shrine_class.with_file(source_io) do |source_io_as_file|
|
55
59
|
definitions_to_create.each do |defn|
|
56
|
-
deriv_bytestream = defn.call(original_file:
|
60
|
+
deriv_bytestream = defn.call(original_file: source_io_as_file, attacher: shrine_attacher)
|
57
61
|
|
58
62
|
if deriv_bytestream
|
59
|
-
|
60
|
-
cleanup_returned_io(deriv_bytestream)
|
63
|
+
derivatives[defn.key] = deriv_bytestream
|
61
64
|
end
|
62
65
|
|
63
|
-
|
66
|
+
# may not need this but it doesn't hurt...
|
67
|
+
source_io.rewind
|
64
68
|
end
|
65
|
-
mark_derivatives_created! if mark_created
|
66
69
|
end
|
70
|
+
|
71
|
+
derivatives
|
67
72
|
end
|
68
73
|
|
69
74
|
private
|
@@ -83,7 +88,7 @@ class Kithe::Asset::DerivativeCreator
|
|
83
88
|
candidates = definitions.find_all do |defn|
|
84
89
|
(only.nil? ? defn.default_create : only.include?(defn.key)) &&
|
85
90
|
(except.nil? || ! except.include?(defn.key)) &&
|
86
|
-
defn.
|
91
|
+
defn.applies_to_content_type?(shrine_attacher.file.content_type)
|
87
92
|
end
|
88
93
|
|
89
94
|
# Now we gotta filter out any duplicate keys based on our priority rules, but keep
|
@@ -107,39 +112,4 @@ class Kithe::Asset::DerivativeCreator
|
|
107
112
|
# Now we uniq keeping last defn
|
108
113
|
candidates.reverse.uniq {|d| d.key }.reverse
|
109
114
|
end
|
110
|
-
|
111
|
-
def cleanup_returned_io(io)
|
112
|
-
if io.respond_to?(:close!)
|
113
|
-
# it's a Tempfile, clean it up now
|
114
|
-
io.close!
|
115
|
-
elsif io.is_a?(File)
|
116
|
-
# It's a File, close it and delete it.
|
117
|
-
io.close
|
118
|
-
File.unlink(io.path)
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
# Sets kithe asset metadata "derivatives_created" to `true`, so
|
123
|
-
# code can know that we're finished creating all `default_create`
|
124
|
-
# derivatives.
|
125
|
-
#
|
126
|
-
# Uses a db-level atomic jsonb update and db-locking to make sure it can do this
|
127
|
-
# without overwriting any other metadata changes, safely.
|
128
|
-
def mark_derivatives_created!
|
129
|
-
asset.transaction do
|
130
|
-
unless asset.acquire_lock_on_sha
|
131
|
-
# asset bytestream has changed
|
132
|
-
return nil
|
133
|
-
end
|
134
|
-
|
135
|
-
sql = <<~SQL
|
136
|
-
UPDATE "#{Kithe::Asset.table_name}"
|
137
|
-
SET file_data = jsonb_set(file_data, '{metadata, derivatives_created}', 'true')
|
138
|
-
WHERE id = '#{asset.id}'
|
139
|
-
SQL
|
140
|
-
|
141
|
-
#ActiveRecord::Base.connection.exec_update("update table set f1=#{ActiveRecord::Base.sanitize(f1)}")
|
142
|
-
Kithe::Asset.connection.execute(sql)
|
143
|
-
end
|
144
|
-
end
|
145
115
|
end
|