Class: Rack::MiniProfiler::MemoryStore

Inherits:
AbstractStore show all
Defined in:
lib/mini_profiler/storage/memory_store.rb

Defined Under Namespace

Classes: CacheCleanupThread

Constant Summary collapse

EXPIRES_IN_SECONDS =
60 * 60 * 24
CLEANUP_INTERVAL =
10
CLEANUP_CYCLE =
3600

Constants inherited from AbstractStore

AbstractStore::MAX_TOKEN_AGE

Instance Method Summary collapse

Methods inherited from AbstractStore

#diagnostics, #snapshots_group, #snapshots_overview

Constructor Details

#initialize(args = nil) ⇒ MemoryStore

Returns a new instance of MemoryStore.



52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/mini_profiler/storage/memory_store.rb', line 52

def initialize(args = nil)
  args ||= {}
  @expires_in_seconds = args.fetch(:expires_in) { EXPIRES_IN_SECONDS }

  @token1, @token2, @cycle_at = nil
  @snapshots_cycle = 0
  @snapshot_groups = {}
  @snapshots = []

  initialize_locks
  initialize_cleanup_thread(args)
end

Instance Method Details

#allowed_tokensObject



132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/mini_profiler/storage/memory_store.rb', line 132

def allowed_tokens
  @token_lock.synchronize do

    unless @cycle_at && (@cycle_at > Process.clock_gettime(Process::CLOCK_MONOTONIC))
      @token2 = @token1
      @token1 = SecureRandom.hex
      @cycle_at = Process.clock_gettime(Process::CLOCK_MONOTONIC) + Rack::MiniProfiler::AbstractStore::MAX_TOKEN_AGE
    end

    [@token1, @token2].compact

  end
end

#cleanup_cacheObject



125
126
127
128
129
130
# File 'lib/mini_profiler/storage/memory_store.rb', line 125

def cleanup_cache
  expire_older_than = ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - @expires_in_seconds) * 1000).to_i
  @timer_struct_lock.synchronize {
    @timer_struct_cache.delete_if { |k, v| v[:started] < expire_older_than }
  }
end

#fetch_snapshots_group(group_name) ⇒ Object



204
205
206
207
208
209
210
211
212
213
# File 'lib/mini_profiler/storage/memory_store.rb', line 204

def fetch_snapshots_group(group_name)
  @snapshots_lock.synchronize do
    group = @snapshot_groups[group_name]
    if group
      group[:snapshots].dup
    else
      []
    end
  end
end

#fetch_snapshots_overviewObject



190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/mini_profiler/storage/memory_store.rb', line 190

def fetch_snapshots_overview
  @snapshots_lock.synchronize do
    groups = {}
    @snapshot_groups.each do |name, group|
      groups[name] = {
        worst_score: group[:worst_score],
        best_score: group[:best_score],
        snapshots_count: group[:snapshots].size
      }
    end
    groups
  end
end

#get_unviewed_ids(user) ⇒ Object



119
120
121
122
123
# File 'lib/mini_profiler/storage/memory_store.rb', line 119

def get_unviewed_ids(user)
  @user_view_lock.synchronize {
    @user_view_cache[user]
  }
end

#initialize_cleanup_thread(args = {}) ⇒ Object

FIXME: use weak ref, trouble it may be broken in 1.9 so need to use the ‘ref’ gem



76
77
78
79
80
81
82
83
84
85
# File 'lib/mini_profiler/storage/memory_store.rb', line 76

def initialize_cleanup_thread(args = {})
  cleanup_interval = args.fetch(:cleanup_interval) { CLEANUP_INTERVAL }
  cleanup_cycle    = args.fetch(:cleanup_cycle)    { CLEANUP_CYCLE }
  t = CacheCleanupThread.new(cleanup_interval, cleanup_cycle, self) do
    until Thread.current[:should_exit] do
      Thread.current.sleepy_run
    end
  end
  at_exit { t[:should_exit] = true }
end

#initialize_locksObject



65
66
67
68
69
70
71
72
73
# File 'lib/mini_profiler/storage/memory_store.rb', line 65

def initialize_locks
  @token_lock           = Mutex.new
  @timer_struct_lock    = Mutex.new
  @user_view_lock       = Mutex.new
  @snapshots_cycle_lock = Mutex.new
  @snapshots_lock       = Mutex.new
  @timer_struct_cache   = {}
  @user_view_cache      = {}
end

#load(id) ⇒ Object



93
94
95
96
97
# File 'lib/mini_profiler/storage/memory_store.rb', line 93

def load(id)
  @timer_struct_lock.synchronize {
    @timer_struct_cache[id]
  }
end

#load_snapshot(id, group_name) ⇒ Object



215
216
217
218
219
220
221
222
# File 'lib/mini_profiler/storage/memory_store.rb', line 215

def load_snapshot(id, group_name)
  @snapshots_lock.synchronize do
    group = @snapshot_groups[group_name]
    if group
      group[:snapshots].find { |s| s[:id] == id }
    end
  end
end

#push_snapshot(page_struct, group_name, config) ⇒ Object



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/mini_profiler/storage/memory_store.rb', line 158

def push_snapshot(page_struct, group_name, config)
  @snapshots_lock.synchronize do
    group = @snapshot_groups[group_name]
    if !group
      @snapshot_groups[group_name] = {
        worst_score: page_struct.duration_ms,
        best_score: page_struct.duration_ms,
        snapshots: [page_struct]
      }
      if @snapshot_groups.size > config.max_snapshot_groups
        group_keys = @snapshot_groups.keys
        group_keys.sort_by! do |key|
          @snapshot_groups[key][:worst_score]
        end
        group_keys.reverse!
        group_keys.pop(group_keys.size - config.max_snapshot_groups)
        @snapshot_groups = @snapshot_groups.slice(*group_keys)
      end
    else
      snapshots = group[:snapshots]
      snapshots << page_struct
      snapshots.sort_by!(&:duration_ms)
      snapshots.reverse!
      if snapshots.size > config.max_snapshots_per_group
        snapshots.pop(snapshots.size - config.max_snapshots_per_group)
      end
      group[:worst_score] = snapshots[0].duration_ms
      group[:best_score] = snapshots[-1].duration_ms
    end
  end
end

#save(page_struct) ⇒ Object



87
88
89
90
91
# File 'lib/mini_profiler/storage/memory_store.rb', line 87

def save(page_struct)
  @timer_struct_lock.synchronize {
    @timer_struct_cache[page_struct[:id]] = page_struct
  }
end

#set_all_unviewed(user, ids) ⇒ Object



113
114
115
116
117
# File 'lib/mini_profiler/storage/memory_store.rb', line 113

def set_all_unviewed(user, ids)
  @user_view_lock.synchronize {
    @user_view_cache[user] = ids
  }
end

#set_unviewed(user, id) ⇒ Object



99
100
101
102
103
104
# File 'lib/mini_profiler/storage/memory_store.rb', line 99

def set_unviewed(user, id)
  @user_view_lock.synchronize {
    @user_view_cache[user] ||= []
    @user_view_cache[user] << id
  }
end

#set_viewed(user, id) ⇒ Object



106
107
108
109
110
111
# File 'lib/mini_profiler/storage/memory_store.rb', line 106

def set_viewed(user, id)
  @user_view_lock.synchronize {
    @user_view_cache[user] ||= []
    @user_view_cache[user].delete(id)
  }
end

#should_take_snapshot?(period) ⇒ Boolean

Returns:

  • (Boolean)


146
147
148
149
150
151
152
153
154
155
156
# File 'lib/mini_profiler/storage/memory_store.rb', line 146

def should_take_snapshot?(period)
  @snapshots_cycle_lock.synchronize do
    @snapshots_cycle += 1
    if @snapshots_cycle % period == 0
      @snapshots_cycle = 0
      true
    else
      false
    end
  end
end