Welcome to mirror list, hosted at ThFree Co, Russian Federation.

20230328111013_re_migrate_redis_slot_keys.rb « post_migrate « db - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 71ab958b601d1c0659c89ca40608bcc1f163eb1d (plain)
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
56
57
58
59
60
61
62
63
64
65
66
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# frozen_string_literal: true

class ReMigrateRedisSlotKeys < Gitlab::Database::Migration[2.1]
  disable_ddl_transaction!

  DAILY_EVENTS =
    %w[g_edit_by_web_ide
      g_edit_by_sfe
      g_edit_by_snippet_ide
      g_edit_by_live_preview
      wiki_action
      design_action
      project_action
      git_write_action
      merge_request_action
      i_source_code_code_intelligence
      g_project_management_issue_title_changed
      g_project_management_issue_description_changed
      g_project_management_issue_assignee_changed
      g_project_management_issue_made_confidential
      g_project_management_issue_made_visible
      g_project_management_issue_created
      g_project_management_issue_closed
      g_project_management_issue_reopened
      g_project_management_issue_label_changed
      g_project_management_issue_milestone_changed
      g_project_management_issue_cross_referenced
      g_project_management_issue_moved
      g_project_management_issue_related
      g_project_management_issue_unrelated
      g_project_management_issue_marked_as_duplicate
      g_project_management_issue_locked
      g_project_management_issue_unlocked
      g_project_management_issue_designs_added
      g_project_management_issue_designs_modified
      g_project_management_issue_designs_removed
      g_project_management_issue_due_date_changed
      g_project_management_issue_design_comments_removed
      g_project_management_issue_time_estimate_changed
      g_project_management_issue_time_spent_changed
      g_project_management_issue_comment_added
      g_project_management_issue_comment_edited
      g_project_management_issue_comment_removed
      g_project_management_issue_cloned
      g_geo_proxied_requests
      approval_project_rule_created
      g_project_management_issue_added_to_epic
      g_project_management_issue_changed_epic
      g_project_management_issue_health_status_changed
      g_project_management_issue_iteration_changed
      g_project_management_issue_removed_from_epic
      g_project_management_issue_weight_changed
      g_geo_proxied_requests
      g_project_management_users_creating_epic_boards
      g_project_management_users_viewing_epic_boards
      g_project_management_users_updating_epic_board_names
      g_project_management_epic_created
      project_management_users_unchecking_epic_task
      project_management_users_checking_epic_task
      g_project_management_users_updating_epic_titles
      g_project_management_users_updating_epic_descriptions
      g_project_management_users_creating_epic_notes
      g_project_management_users_updating_epic_notes
      g_project_management_users_destroying_epic_notes
      g_project_management_users_awarding_epic_emoji
      g_project_management_users_removing_epic_emoji
      g_project_management_users_setting_epic_start_date_as_fixed
      g_project_management_users_updating_fixed_epic_start_date
      g_project_management_users_setting_epic_start_date_as_inherited
      g_project_management_users_setting_epic_due_date_as_fixed
      g_project_management_users_updating_fixed_epic_due_date
      g_project_management_users_setting_epic_due_date_as_inherited
      g_project_management_epic_issue_added
      g_project_management_epic_issue_removed
      g_project_management_epic_issue_moved_from_project
      g_project_management_users_updating_epic_parent
      g_project_management_epic_closed
      g_project_management_epic_reopened
      g_project_management_issue_promoted_to_epic
      g_project_management_users_setting_epic_confidential
      g_project_management_users_setting_epic_visible
      g_project_management_epic_users_changing_labels
      g_project_management_epic_destroyed
      g_project_management_epic_cross_referenced
      g_project_management_users_epic_issue_added_from_epic
      g_project_management_epic_related_added
      g_project_management_epic_related_removed
      g_project_management_epic_blocking_added
      g_project_management_epic_blocking_removed
      g_project_management_epic_blocked_added
      g_project_management_epic_blocked_removed].freeze

  def up
    Gitlab::UsageDataCounters::HLLRedisCounter.known_events.each do |event|
      if DAILY_EVENTS.include?(event[:name].to_s)
        migrate_daily_aggregated(event)
      else
        migrate_weekly_aggregated(event)
      end
    end
  end

  def down
    # no-op
  end

  private

  def migrate_daily_aggregated(event)
    days_back = 29.days
    start_date = Date.today - days_back - 1.day
    end_date = Date.today + 1.day

    (start_date..end_date).each do |date|
      rename_key(event, date)
    end
  end

  def migrate_weekly_aggregated(event)
    weeks_back = Gitlab::UsageDataCounters::HLLRedisCounter::DEFAULT_WEEKLY_KEY_EXPIRY_LENGTH
    start_date = (Date.today - weeks_back).beginning_of_week - 1.day
    end_date = Date.today.end_of_week + 1.day

    (start_date..end_date).step(7).each { |date| rename_key(event, date) }
  end

  def rename_key(event, date)
    old_key = old_redis_key(event, date)
    new_key = new_redis_key(event, date)

    # cannot simply rename due to different slots
    Gitlab::Redis::SharedState.with do |redis|
      hll_blob = redis.get(old_key)

      break unless hll_blob

      temp_key = new_key + "_#{Time.current.to_i}"
      ttl = redis.ttl(old_key)
      ttl = ttl > 0 ? ttl : Gitlab::UsageDataCounters::HLLRedisCounter.send(:expiry, event)

      redis.multi do |multi|
        multi.set(temp_key, hll_blob, ex: 1.day.to_i)
        multi.pfmerge(new_key, new_key, temp_key)
        multi.expire(new_key, ttl)
      end

      redis.del(temp_key)
    end
  end

  def old_redis_key(event, time)
    name_with_slot = if event[:redis_slot].present?
                       event[:name].to_s.gsub(event[:redis_slot], "{#{event[:redis_slot]}}")
                     else
                       "{#{event[:name]}}"
                     end

    apply_time_aggregation(name_with_slot, time, event)
  end

  def new_redis_key(event, time)
    key = "{hll_counters}_#{event[:name]}"
    apply_time_aggregation(key, time, event)
  end

  def apply_time_aggregation(key, time, event)
    if DAILY_EVENTS.include?(event[:name].to_s)
      year_day = time.strftime('%G-%j')
      "#{year_day}-#{key}"
    else
      year_week = time.strftime('%G-%V')
      "#{key}-#{year_week}"
    end
  end
end