Class: Flycal::CacheKey

Inherits:
Object
  • Object
show all
Defined in:
lib/flycal/cache_key.rb

Overview

Builds stable cache keys for search/slots from fully resolved params (defaults applied, just before Google API calls).

Constant Summary collapse

DEFAULT_TTL_MINUTES =
5
CACHED_COMMANDS =

Commands / CLI verbs / API paths that use response caching. Everything else (version, calendars, login, config, …) is uncached.

%w[search slots].freeze
SKIP_KEYS =
%w[
  nocache cache_status cache_key events totals groups calendar_names raw
].freeze

Class Method Summary collapse

Class Method Details

.cached?(command) ⇒ Boolean

Returns:

  • (Boolean)


25
26
27
# File 'lib/flycal/cache_key.rb', line 25

def cached?(command)
  CACHED_COMMANDS.include?(command.to_s)
end

.cached_commandsObject



21
22
23
# File 'lib/flycal/cache_key.rb', line 21

def cached_commands
  CACHED_COMMANDS
end

.canonical_json(params) ⇒ Object



34
35
36
# File 'lib/flycal/cache_key.rb', line 34

def canonical_json(params)
  JSON.generate(deep_sort(normalize(params)))
end

.deep_sort(value) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/flycal/cache_key.rb', line 66

def deep_sort(value)
  case value
  when Hash
    value.keys.map(&:to_s).sort.each_with_object({}) do |k, out|
      # Hash may have symbol keys after normalize we use strings
      raw_key = value.key?(k) ? k : value.keys.find { |x| x.to_s == k }
      out[k] = deep_sort(value[raw_key])
    end
  when Array
    value.map { |v| deep_sort(v) }
  else
    value
  end
end

.generate(command, params) ⇒ Object



29
30
31
32
# File 'lib/flycal/cache_key.rb', line 29

def generate(command, params)
  digest = Digest::SHA256.hexdigest(canonical_json(params))
  "flycal-#{command}-#{digest}"
end

.normalize(value) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/flycal/cache_key.rb', line 38

def normalize(value)
  case value
  when Hash
    value.each_with_object({}) do |(k, v), out|
      key = k.to_s
      next if SKIP_KEYS.include?(key)

      out[key] = normalize(v)
    end
  when Array
    value.map { |v| normalize(v) }
  when Time, DateTime
    value.respond_to?(:iso8601) ? value.iso8601 : value.to_s
  when Date
    value.iso8601
  when nil, TrueClass, FalseClass, Numeric, String
    value
  else
    if value.respond_to?(:iso8601)
      value.iso8601
    elsif value.respond_to?(:to_h) && !value.is_a?(String)
      normalize(value.to_h)
    else
      value.to_s
    end
  end
end