Class: CopyTunerClient::Cache

Inherits:
Object
  • Object
show all
Defined in:
lib/copy_tuner_client/cache.rb

Overview

Manages synchronization of copy between I18nBackend and Client. Acts like a Hash. Applications using the client will not need to interact with this class directly.

Responsible for locking down access to data used by both threads.

Constant Summary collapse

STATUS_NOT_READY =
:not_ready
STATUS_PENDING =
:pending
STATUS_READY =
:ready

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(client, options) ⇒ Cache

Usually instantiated when CopyTunerClient::Configuration#apply is invoked.

Parameters:

  • client (Client)

    the client used to fetch and upload data

  • options (Hash)

Options Hash (options):

  • :logger (Logger)

    where errors should be logged



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/copy_tuner_client/cache.rb', line 19

def initialize(client, options)
  @client = client
  @logger = options[:logger]
  @mutex = Mutex.new
  @exclude_key_regexp = options[:exclude_key_regexp]
  @local_first_key_regexp = options[:local_first_key_regexp]
  @upload_disabled = options[:upload_disabled]
  @ignored_keys = options.fetch(:ignored_keys, [])
  @ignored_key_handler = options.fetch(:ignored_key_handler, -> (e) { raise e })
  @locales = Array(options[:locales]).map(&:to_s)
  # mutable states
  @blurbs = {}
  @blank_keys = Set.new
  @queued = {}
  @status = STATUS_NOT_READY
end

Instance Attribute Details

#blurbsObject (readonly)

Returns the value of attribute blurbs.



146
147
148
# File 'lib/copy_tuner_client/cache.rb', line 146

def blurbs
  @blurbs
end

#last_downloaded_atObject (readonly)

Returns the value of attribute last_downloaded_at.



146
147
148
# File 'lib/copy_tuner_client/cache.rb', line 146

def last_downloaded_at
  @last_downloaded_at
end

#last_uploaded_atObject (readonly)

Returns the value of attribute last_uploaded_at.



146
147
148
# File 'lib/copy_tuner_client/cache.rb', line 146

def last_uploaded_at
  @last_uploaded_at
end

#queuedObject (readonly)

Returns the value of attribute queued.



146
147
148
# File 'lib/copy_tuner_client/cache.rb', line 146

def queued
  @queued
end

Instance Method Details

#[](key) ⇒ String

Returns content for the given blurb.

Parameters:

  • key (String)

    the key of the desired blurb

Returns:

  • (String)

    the contents of the blurb



39
40
41
# File 'lib/copy_tuner_client/cache.rb', line 39

def [](key)
  lock { @blurbs[key] }
end

#[]=(key, value) ⇒ Object

Sets content for the given blurb. The content will be pushed to the server on the next flush.

Parameters:

  • key (String)

    the key of the blurb to update

  • value (String)

    the new contents of the blurb



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/copy_tuner_client/cache.rb', line 47

def []=(key, value)
  return if @exclude_key_regexp && key.match?(@exclude_key_regexp)
  return unless key.include?('.')
  return if @locales.present? && !@locales.member?(key.split('.').first)
  return if @upload_disabled

  # NOTE: config/locales以下のファイルに除外キーが残っていた場合の対応
  key_without_locale = key.split('.')[1..].join('.')
  # NOTE: local_first_key_regexp にマッチするキーは copy_tuner と完全分離するためアップロードしない
  return if @local_first_key_regexp && key_without_locale.match?(@local_first_key_regexp)

  if @ignored_keys.include?(key_without_locale)
    @ignored_key_handler.call(IgnoredKey.new("Ignored key: #{key_without_locale}"))
  end

  lock do
    return if @blank_keys.member?(key) || @blurbs.key?(key)

    @queued[key] = value
  end
end

#downloadObject



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/copy_tuner_client/cache.rb', line 120

def download
  @status = STATUS_PENDING unless ready?

  res = client.download(cache_fallback: pending?) do |downloaded_blurbs|
    blank_blurbs, blurbs = downloaded_blurbs.partition { |_key, value| value == '' }
    lock do
      @blank_keys = Set.new(blank_blurbs.map(&:first))
      @blurbs = blurbs.to_h
    end
  end

  @last_downloaded_at = Time.now.utc
  @status = STATUS_READY unless ready?

  res
rescue ConnectionError => e
  logger.error e.message
  raise e unless ready?
end

#exportString

Yaml representation of all blurbs

Returns:

  • (String)

    yaml



77
78
79
80
# File 'lib/copy_tuner_client/cache.rb', line 77

def export
  tree_hash = to_tree_hash
  tree_hash.present? ? tree_hash.to_yaml : nil
end

#flushObject



108
109
110
111
112
113
114
115
116
117
118
# File 'lib/copy_tuner_client/cache.rb', line 108

def flush
  res = with_queued_changes do |queued|
    client.upload queued
  end

  @last_uploaded_at = Time.now.utc

  res
rescue ConnectionError => e
  logger.error e.message
end

#inspectObject



148
149
150
# File 'lib/copy_tuner_client/cache.rb', line 148

def inspect
  "#<CopyTunerClient::Cache:#{object_id}>"
end

#keysArray<String>

Keys for all blurbs stored on the server.

Returns:

  • (Array<String>)

    keys



71
72
73
# File 'lib/copy_tuner_client/cache.rb', line 71

def keys
  lock { @blurbs.keys }
end

#pending?Boolean

Returns:

  • (Boolean)


152
153
154
# File 'lib/copy_tuner_client/cache.rb', line 152

def pending?
  @status == STATUS_PENDING
end

#ready?Boolean

Returns:

  • (Boolean)


156
157
158
# File 'lib/copy_tuner_client/cache.rb', line 156

def ready?
  @status == STATUS_READY
end

#syncObject

Downloads and then flushes



141
142
143
144
# File 'lib/copy_tuner_client/cache.rb', line 141

def sync
  download
  flush
end

#to_tree_hashHash

ツリー構造のハッシュを返す(I18nBackend用)

Returns:

  • (Hash)

    ツリー構造に変換されたblurbs



84
85
86
# File 'lib/copy_tuner_client/cache.rb', line 84

def to_tree_hash
  lock { @blurbs.present? ? DottedHash.to_h(@blurbs) : {} }
end

#versionString?

キャッシュの更新バージョンを返す(ツリーキャッシュの無効化判定用)ETags を使用してサーバーサイドの更新を検知

Returns:

  • (String, nil)

    現在のETag値



91
92
93
# File 'lib/copy_tuner_client/cache.rb', line 91

def version
  client.etag
end

#wait_for_downloadObject

Waits until the first download has finished.



96
97
98
99
100
101
102
103
104
105
106
# File 'lib/copy_tuner_client/cache.rb', line 96

def wait_for_download
  return unless pending?

  logger.info 'Waiting for first download'

  if logger.respond_to? :flush
    logger.flush
  end

  sleep 0.1 while pending?
end