diff options
author | Eugen Rochko <eugen@zeonfederated.com> | 2017-10-08 17:34:34 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-10-08 17:34:34 +0200 |
commit | 0717d9b3e6904a4dcd5d2dc9e680cc5b21c50e51 (patch) | |
tree | fc95b8a715b8035231a6aa009bc82b3662ab236c /lib | |
parent | 6e4046fc3f3973ba0b6994930a8b58726e507003 (diff) |
Set snowflake IDs for backdated statuses (#5260)
- Rename Mastodon::TimestampIds into Mastodon::Snowflake for clarity - Skip for statuses coming from inbox, aka delivered in real-time - Skip for statuses that claim to be from the future
Diffstat (limited to 'lib')
-rw-r--r-- | lib/mastodon/snowflake.rb (renamed from lib/mastodon/timestamp_ids.rb) | 33 | ||||
-rw-r--r-- | lib/tasks/db.rake | 6 |
2 files changed, 35 insertions, 4 deletions
diff --git a/lib/mastodon/timestamp_ids.rb b/lib/mastodon/snowflake.rb index 3b048a50c..219e323d4 100644 --- a/lib/mastodon/timestamp_ids.rb +++ b/lib/mastodon/snowflake.rb @@ -1,8 +1,32 @@ # frozen_string_literal: true -module Mastodon::TimestampIds +module Mastodon::Snowflake DEFAULT_REGEX = /timestamp_id\('(?<seq_prefix>\w+)'/ + class Callbacks + def self.around_create(record) + now = Time.now.utc + + if record.created_at.nil? || record.created_at >= now || record.created_at == record.updated_at + yield + else + record.id = Mastodon::Snowflake.id_at(record.created_at) + tries = 0 + + begin + yield + rescue ActiveRecord::RecordNotUnique + raise if tries > 100 + + tries += 1 + record.id += rand(100) + + retry + end + end + end + end + class << self # Our ID will be composed of the following: # 6 bytes (48 bits) of millisecond-level timestamp @@ -114,6 +138,13 @@ module Mastodon::TimestampIds end end + def id_at(timestamp) + id = timestamp.to_i * 1000 + rand(1000) + id = id << 16 + id += rand(2**16) + id + end + private def already_defined? diff --git a/lib/tasks/db.rake b/lib/tasks/db.rake index 6af6bb6fb..32039c31d 100644 --- a/lib/tasks/db.rake +++ b/lib/tasks/db.rake @@ -1,6 +1,6 @@ # frozen_string_literal: true -require Rails.root.join('lib', 'mastodon', 'timestamp_ids') +require_relative '../mastodon/snowflake' def each_schema_load_environment # If we're in development, also run this for the test environment. @@ -63,13 +63,13 @@ namespace :db do task :define_timestamp_id do each_schema_load_environment do - Mastodon::TimestampIds.define_timestamp_id + Mastodon::Snowflake.define_timestamp_id end end task :ensure_id_sequences_exist do each_schema_load_environment do - Mastodon::TimestampIds.ensure_id_sequences_exist + Mastodon::Snowflake.ensure_id_sequences_exist end end end |