diff --git a/Gemfile.lock b/Gemfile.lock index b0346e8..3d0b457 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,6 +1,6 @@ GIT remote: https://github.com/rails/rails.git - revision: 95deab7b439abba23fdc4bd659116dab5dbe2606 + revision: 44673c80bde08f17659a709279972827ffa0ae64 branch: main specs: actioncable (8.1.0.alpha) @@ -292,7 +292,7 @@ GEM activejob (>= 7.2) activerecord (>= 7.2) railties (>= 7.2) - solid_queue (1.0.2) + solid_queue (1.1.0) activejob (>= 7.1) activerecord (>= 7.1) concurrent-ruby (>= 1.3.1) diff --git a/app/models/conversation.rb b/app/models/conversation.rb index a2a129e..5c6fb23 100644 --- a/app/models/conversation.rb +++ b/app/models/conversation.rb @@ -9,6 +9,10 @@ class Conversation < ApplicationRecord dependent: :restrict_with_exception def latest_event - events.order(id: :desc).first + if latest_eid.blank? + nil + else + Event.find(latest_eid) + end end end diff --git a/app/models/event.rb b/app/models/event.rb index 43a7ee6..a2bb27c 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -11,16 +11,16 @@ class Event < ApplicationRecord belongs_to :conversation, foreign_key: %i[pubkey session], required: true, autosave: true has_one :merkle_node, dependent: :restrict_with_exception - after_create :add_to_merkle_tree - # A publisher must not send events in the same time which makes harder to sort them. validates :created_at, - presence: true, + presence: true + validates :created_at, comparison: { greater_than_or_equal_to: ->(current) { current.conversation&.latest_event_created_at || 0 } - } + }, + if: :new_record? validates :session, presence: true, @@ -36,6 +36,15 @@ class Event < ApplicationRecord format: { with: /\A\h+\z/ }, allow_nil: true + validate if: :new_record? do + prev_id = tags.find { |tag| tag[0] == "prev_id" }&.[](1) + next if prev_id.blank? + + if self.connection.latest_eid != prev_id + errors.add :prev_id, :invalid + end + end + before_validation on: :create do self.session = tags.find { |tag| tag[0] == "s" }&.[](1) self.topic = tags.find { |tag| tag[0] == "t" }&.[](1) @@ -48,10 +57,13 @@ class Event < ApplicationRecord end after_validation on: :create do + self.conversation.latest_eid = eid self.conversation.latest_event_created_at = created_at self.conversation.events_count += 1 end + after_create :add_to_merkle_tree + def merkle_tree_hash Digest::Keccak256.digest([pubkey, topic, session].join) end diff --git a/db/migrate/20240325200100_create_conversations.rb b/db/migrate/20240325200100_create_conversations.rb index e20f05f..aa81bf7 100644 --- a/db/migrate/20240325200100_create_conversations.rb +++ b/db/migrate/20240325200100_create_conversations.rb @@ -6,10 +6,12 @@ def change t.string :pubkey, null: false t.string :session, null: false - t.integer :lock_version - t.datetime :latest_event_created_at t.integer :events_count + t.string :latest_eid + t.datetime :latest_event_created_at + + t.integer :lock_version t.timestamps end end diff --git a/db/schema.rb b/db/schema.rb index 9201790..0bb4188 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -17,9 +17,10 @@ create_table "conversations", primary_key: ["pubkey", "session"], force: :cascade do |t| t.string "pubkey", null: false t.string "session", null: false - t.integer "lock_version" - t.datetime "latest_event_created_at" t.integer "events_count" + t.string "latest_eid" + t.datetime "latest_event_created_at" + t.integer "lock_version" t.datetime "created_at", null: false t.datetime "updated_at", null: false end