Module: CleanupJob::SmartCleanup

Included in:
CleanupJob
Defined in:
app/jobs/cleanup_job.rb

Constant Summary collapse

MAX_ITERATIONS =
50
MIN_ERROR_TRUSTED =
0.01

Instance Method Summary collapse

Instance Method Details

#cleanup_period(from, to, limit) ⇒ Object


124
125
126
# File 'app/jobs/cleanup_job.rb', line 124

def cleanup_period(from, to, limit)
  obj = Post.created_between(from, to).unpopular.limit(limit).destroy_all
end

#divide_period_into_parts(from, to, n = 1) ⇒ Object


42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'app/jobs/cleanup_job.rb', line 42

def divide_period_into_parts(from, to, n = 1)
  periods = [[from, to]]

  n.times do
    new_periods = []

    periods.each_with_index do |period, _index|
      from = period[0]
      to = period[1]

      m = median(from, to)

      new_periods << [from, m]
      new_periods << [m, to]
    end

    periods = new_periods
  end

  periods
end

#median(from, to) ⇒ Object


67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'app/jobs/cleanup_job.rb', line 67

def median(from, to)
  from = from.to_f
  to = to.to_f

  # область поиска
  median_from = from
  median_to = to

  current = -> { (median_from + median_to) / 2 }
  count_older = -> { Post.created_between(Time.at(from), Time.at(current.call)).count }
  count_newer = -> { Post.created_between(Time.at(current.call), Time.at(to)).count }
  error = -> { (count_older.call - count_newer.call).abs.to_f / ((count_older.call + count_newer.call).abs / 2) }

  i = 0
  loop do
    break if i > MAX_ITERATIONS
    break if error.call < MIN_ERROR_TRUSTED

    if count_older.call < count_newer.call
      median_from = current.call
    else
      median_to = current.call
    end

    i += 1
  end

  Time.at current.call
end

#smart_cleanupObject

делим весь период на 16 частей очищаем каждый период, кроме самого последнего


99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'app/jobs/cleanup_job.rb', line 99

def smart_cleanup
  count = 0

  delete_in_each_period = ((space_needed - space_available).to_f / 15).round
  periods = divide_period_into_parts(Post.minimum(:created_at), Post.maximum(:created_at), 4)
  periods.pop

  from = periods[0][0]
  to = periods[-1][1]
  obj = Post.where(views: 0).limit(space_needed - space_available).created_between(from, to).destroy_all.size
  count += obj.size
  EventTracker.track('Jobs', 'Cleanup unused', "#{from} - #{to}", obj.size)

  return unless need_cleanup?

  delete_in_each_period = ((space_needed - space_available).to_f / 15).round
  divide_period_into_parts(Post.minimum(:created_at), Post.maximum(:created_at), 4)[0..-2].each do |period|
    obj = cleanup_period(period[0], period[1], delete_in_each_period)
    count += obj.size
    EventTracker.track('Jobs', 'Cleanup smart', "#{period[0]} - #{period[1]}", obj.size)
  end

  count
end