-
Notifications
You must be signed in to change notification settings - Fork 121
/
garbage_collector.rb
55 lines (51 loc) · 2.08 KB
/
garbage_collector.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
module Unread
class GarbageCollector
def initialize(readable_class)
@readable_class = readable_class.readable_parent
end
attr_reader :readable_class
def run!
ReadMark.reader_classes.each do |reader_class|
readers_to_cleanup(reader_class).find_each do |reader|
if oldest_timestamp = readable_class.read_scope(reader).
unread_by(reader).
minimum(readable_class.readable_options[:on])
# There are unread items, so update the global read_mark for this reader to the oldest
# unread item and delete older read_marks
update_read_marks_for_user(reader, oldest_timestamp)
else
# There is no unread item, so deletes all markers and move global timestamp
readable_class.reset_read_marks_for_user(reader)
end
end
end
end
private
# Not for every reader a cleanup is needed.
# Look for those readers with at least one single read mark
def readers_to_cleanup(reader_class)
reader_class.
reader_scope.
joins(:read_marks).
where(ReadMark.table_name => { readable_type: readable_class.name }).
group("#{ReadMark.quoted_table_name}.reader_type, #{ReadMark.quoted_table_name}.reader_id, #{reader_class.quoted_table_name}.#{reader_class.quoted_primary_key}").
having("COUNT(#{ReadMark.quoted_table_name}.id) > 1").
select("#{reader_class.quoted_table_name}.#{reader_class.quoted_primary_key}")
end
def update_read_marks_for_user(reader, timestamp)
ReadMark.transaction do
# Delete markers OLDER than the given timestamp
reader.read_marks.
where(readable_type: readable_class.name).
single.
older_than(timestamp).
delete_all
# Change the global timestamp for this reader
rm = reader.read_mark_global(readable_class) || reader.read_marks.build
rm.readable_type = readable_class.name
rm.timestamp = timestamp - 1.second
rm.save!
end
end
end
end