Class: ObjectStorage::PendingDirectUpload

Inherits:
Object
  • Object
show all
Includes:
FogHelpers
Defined in:
lib/object_storage/pending_direct_upload.rb

Constant Summary collapse

KEY =
'pending_direct_uploads'
MAX_UPLOAD_DURATION =
3.hours.freeze

Class Method Summary collapse

Instance Method Summary collapse

Methods included from FogHelpers

#available?

Constructor Details

#initialize(redis_key:, storage_location_identifier:, object_storage_path:, timestamp:) ⇒ PendingDirectUpload

Returns a new instance of PendingDirectUpload.



89
90
91
92
93
94
# File 'lib/object_storage/pending_direct_upload.rb', line 89

def initialize(redis_key:, storage_location_identifier:, object_storage_path:, timestamp:)
  @redis_key = redis_key
  @storage_location_identifier = storage_location_identifier.to_sym
  @object_storage_path = object_storage_path
  @timestamp = timestamp.to_i
end

Class Method Details

.complete(location_identifier, object_storage_path) ⇒ Object



42
43
44
45
46
47
48
# File 'lib/object_storage/pending_direct_upload.rb', line 42

def self.complete(location_identifier, object_storage_path)
  with_redis do |redis|
    key = redis_key(location_identifier, object_storage_path)
    redis.hdel(KEY, key)
    log_event(:completed, key)
  end
end

.countObject



54
55
56
57
58
# File 'lib/object_storage/pending_direct_upload.rb', line 54

def self.count
  with_redis do |redis|
    redis.hlen(KEY)
  end
end

.eachObject



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/object_storage/pending_direct_upload.rb', line 60

def self.each
  with_redis do |redis|
    redis.hscan_each(KEY) do |entry|
      redis_key, timestamp = entry
      storage_location_identifier, object_storage_path = redis_key.split(':')

      object = new(
        redis_key: redis_key,
        storage_location_identifier: storage_location_identifier,
        object_storage_path: object_storage_path,
        timestamp: timestamp
      )

      yield(object)
    end
  end
end

.exists?(location_identifier, object_storage_path) ⇒ Boolean

Returns:

  • (Boolean)


36
37
38
39
40
# File 'lib/object_storage/pending_direct_upload.rb', line 36

def self.exists?(location_identifier, object_storage_path)
  with_redis do |redis|
    redis.hexists(KEY, redis_key(location_identifier, object_storage_path))
  end
end

.log_event(event, redis_key) ⇒ Object



82
83
84
85
86
87
# File 'lib/object_storage/pending_direct_upload.rb', line 82

def self.log_event(event, redis_key)
  Gitlab::AppLogger.info(
    message: "Pending direct upload #{event}",
    redis_key: redis_key
  )
end

.prepare(location_identifier, object_storage_path) ⇒ Object



10
11
12
13
14
15
16
17
18
19
# File 'lib/object_storage/pending_direct_upload.rb', line 10

def self.prepare(location_identifier, object_storage_path)
  with_redis do |redis|
    # We need to store the location_identifier together with the timestamp to properly delete
    # this object if ever this upload gets stale. The location identifier will be used
    # by the clean up worker to properly generate the storage options through ObjectStorage::Config.for_location
    key = redis_key(location_identifier, object_storage_path)
    redis.hset(KEY, key, Time.current.utc.to_i)
    log_event(:prepared, key)
  end
end

.redis_key(location_identifier, object_storage_path) ⇒ Object



50
51
52
# File 'lib/object_storage/pending_direct_upload.rb', line 50

def self.redis_key(location_identifier, object_storage_path)
  [location_identifier, object_storage_path].join(':')
end

.with_pending_only(location_identifier, object_storage_paths) ⇒ Object



21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/object_storage/pending_direct_upload.rb', line 21

def self.with_pending_only(location_identifier, object_storage_paths)
  with_redis do |redis|
    keys = object_storage_paths.map do |path|
      redis_key(location_identifier, path)
    end

    matches = redis.hmget(KEY, keys)
    index = -1
    object_storage_paths.select do
      index += 1
      matches[index].present?
    end
  end
end

.with_redis(&block) ⇒ Object



78
79
80
# File 'lib/object_storage/pending_direct_upload.rb', line 78

def self.with_redis(&block)
  Gitlab::Redis::SharedState.with(&block) # rubocop:disable CodeReuse/ActiveRecord
end

Instance Method Details

#deleteObject



100
101
102
103
104
105
106
107
# File 'lib/object_storage/pending_direct_upload.rb', line 100

def delete
  delete_object(object_storage_path)

  self.class.with_redis do |redis|
    redis.hdel(self.class::KEY, redis_key)
    self.class.log_event(:deleted, redis_key)
  end
end

#stale?Boolean

Returns:

  • (Boolean)


96
97
98
# File 'lib/object_storage/pending_direct_upload.rb', line 96

def stale?
  timestamp < MAX_UPLOAD_DURATION.ago.utc.to_i
end