У меня есть выделенная служба, используемая для pu sh на отметках времени столбца jsonb
о некоторых событиях.
Конфигурация:
pg: 1.2.2
PostgreSQL: 11.4
Rails: 6.0.2.1
Ruby: 2.6.5
Вот схема моей таблицы:
create_table "invitations", force: :cascade do |t|
t.uuid "uuid", default: -> { "gen_random_uuid()" }, null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.jsonb "notification_statuses", default: {}, null: false
end
Вот типичная jsonb
У меня есть для столбца notification_statuses
:
{emails: [{created_at: "some date", sent_at: "some date2"},
{created_at: "some other date", sent_at: "some other date2"}]}
Вот код:
class MyNotificationManager
def initialize(invitation_id)
@invitation = Invitation.find(invitation_id)
end
def start_new_notification_status(type)
@invitation.with_lock do
@invitation.notification_statuses[type] = [] unless @invitation.notification_statuses.key?(type)
hsh = { created_at: Time.zone.now, sent_at: nil }
@invitation.notification_statuses[type].push(hsh)
@invitation.save!
puts "push #{@invitation.notification_statuses[type].count}"
end
end
end
Вот тест:
describe '#start_new_notification_status' do
subject { MyNotificationManager }
describe "with concurrency" do
let(:concurrency_level) { 4 }
let!(:invitation) { create(:invitation) }
it "updates invitation one at the time" do
expect(ActiveRecord::Base.connection.pool.size).to eq(5)
fail_occurred = false
wait_for_it = true
threads = concurrency_level.times.map do |i|
Thread.new do
true while wait_for_it
begin
serv = subject.new(invitation.id)
serv.start_new_notification_status('emails')
rescue StandardError => err
fail_occurred = true
end
end
end
wait_for_it = false
threads.each(&:join)
expect(fail_occurred).not_to be_truthy
expect(invitation.reload.notification_statuses['emails'].count).to eq(concurrency_level)
end
end
end
Наконец, мой RSpe c logs:
Event::NotificationManager
#start_new_notification_status
with concurrency
push 1
push 2
push 2
push 2
Failure/Error: expect(invitation.reload.notification_statuses['emails'].count).to eq(concurrency_level)
expected: 4
got: 2
Чего мне не хватает? Журналы, очевидно, должны быть:
Event::NotificationManager
#start_new_notification_status
with concurrency
push 1
push 2
push 3
push 4
Вот мои журналы.
(0.5ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = $1 [["key", "schema_sha1"]]
(0.7ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
(0.9ms) BEGIN
(0.3ms) SAVEPOINT active_record_1
Address Create (19.8ms) INSERT INTO "addresses" ("uuid", "line1", "line2", "locality", "zip_postcode", "country_province", "country", "latitude", "longitude", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) RETURNING "id" [["uuid", "6ca512f7-aa9d-4deb-9fce-7ce3e878f5ee"], ["line1", "27862 Kautzer Dam"], ["line2", "Apt. 831"], ["locality", "West Gladys"], ["zip_postcode", "27812-2854"], ["country_province", "North Carolina"], ["country", "Saint Kitts and Nevis"], ["latitude", 6.990987893090221], ["longitude", -79.50793749705787], ["created_at", "2020-04-20 07:49:21.760116"], ["updated_at", "2020-04-20 07:49:21.760116"]]
(0.3ms) RELEASE SAVEPOINT active_record_1
(0.3ms) SAVEPOINT active_record_1
Establishment Create (14.0ms) INSERT INTO "establishments" ("name", "contact_name", "description", "note", "insta_user_name", "address_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING "id" [["name", "Stehr-Donnelly"], ["contact_name", "Narcisa"], ["description", "Asperiores voluptates consequuntur."], ["note", "Dolore qui."], ["insta_user_name", "berta.king"], ["address_id", 1], ["created_at", "2020-04-20 07:49:21.792061"], ["updated_at", "2020-04-20 07:49:21.792061"]]
ActsAsTaggableOn::Tagging Load (0.6ms) SELECT "taggings".* FROM "taggings" WHERE "taggings"."taggable_id" = $1 AND "taggings"."taggable_type" = $2 [["taggable_id", 1], ["taggable_type", "Establishment"]]
(0.2ms) RELEASE SAVEPOINT active_record_1
(0.3ms) SAVEPOINT active_record_1
(1.0ms) SELECT COUNT(*) FROM "events" WHERE "events"."establishment_id" = $1 AND ((start_at <= '2020-04-22 16:05:59' AND end_at >= '2020-04-22 16:05:59' AND end_at <= '2020-04-22 18:05:59') OR
(end_at >= '2020-04-22 18:05:59' AND start_at <= '2020-04-22 18:05:59' AND start_at >= '2020-04-22 16:05:59') OR
(start_at >= '2020-04-22 16:05:59' AND end_at <= '2020-04-22 18:05:59') OR
(start_at <= '2020-04-22 16:05:59' AND end_at >= '2020-04-22 18:05:59')) [["establishment_id", 1]]
Event Create (17.1ms) INSERT INTO "events" ("uuid", "establishment_id", "name", "start_at", "end_at", "max_female_guest", "max_male_guest", "created_at", "updated_at", "published") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) RETURNING "id" [["uuid", "f110cba0-1f97-45ed-bc84-a8bebc73b8f8"], ["establishment_id", 1], ["name", "Clifford Kulas Conroy"], ["start_at", "2020-04-22 16:05:59"], ["end_at", "2020-04-22 18:05:59"], ["max_female_guest", 5], ["max_male_guest", 5], ["created_at", "2020-04-20 07:49:21.830331"], ["updated_at", "2020-04-20 07:49:21.830331"], ["published", true]]
Establishment Update All (0.6ms) UPDATE "establishments" SET "events_count" = COALESCE("events_count", 0) + $1 WHERE "establishments"."id" = $2 [["events_count", 1], ["id", 1]]
(0.2ms) RELEASE SAVEPOINT active_record_1
(0.4ms) SAVEPOINT active_record_1
Area Create (8.1ms) INSERT INTO "areas" ("uuid", "name", "slug", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["uuid", "e13cec8d-4767-490f-a909-f07970006743"], ["name", "Derick Robel"], ["slug", "derick-robel"], ["created_at", "2020-04-20 07:49:21.970034"], ["updated_at", "2020-04-20 07:49:21.970034"]]
(0.3ms) RELEASE SAVEPOINT active_record_1
(0.3ms) SAVEPOINT active_record_1
User Exists? (0.9ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = $1 LIMIT $2 [["email", "vernon@bergstrom.biz"], ["LIMIT", 1]]
User Create (18.8ms) INSERT INTO "users" ("uuid", "email", "encrypted_password", "confirmation_token", "confirmed_at", "confirmation_sent_at", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING "id" [["uuid", "3bb5012a-ff5b-4dc8-b474-98aa06298c5c"], ["email", "vernon@bergstrom.biz"], ["encrypted_password", "$2a$04$dnmdv.wKESDVpFTn9UyqE.uFQwCexFGcmYBdg18HfGrvv0/4xrrQm"], ["confirmation_token", "bfa804e9-cd89-49ba-acb5-3afcfd5425f6"], ["confirmed_at", "2020-04-20 07:49:21.916321"], ["confirmation_sent_at", "2020-04-20 06:49:21.916422"], ["created_at", "2020-04-20 07:49:22.008360"], ["updated_at", "2020-04-20 07:49:22.008360"]]
AreasUser Create (4.8ms) INSERT INTO "areas_users" ("area_id", "user_id") VALUES ($1, $2) [["area_id", 1], ["user_id", 1]]
(0.2ms) RELEASE SAVEPOINT active_record_1
(0.2ms) SAVEPOINT active_record_1
Consumer Create (8.4ms) INSERT INTO "consumers" ("user_id", "first_name", "last_name", "whatsapp_user_name", "phone_number", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id" [["user_id", 1], ["first_name", "Kermit"], ["last_name", "Cremin"], ["whatsapp_user_name", "7a206657-8365-4075-b4e8-b58d421ac2e2"], ["phone_number", "+855 618.798.2641"], ["created_at", "2020-04-20 07:49:22.036784"], ["updated_at", "2020-04-20 07:49:22.036784"]]
(0.3ms) RELEASE SAVEPOINT active_record_1
(0.2ms) SAVEPOINT active_record_1
Guest Create (18.1ms) INSERT INTO "guests" ("uuid", "gender", "birthdate", "profession", "insta_user_name", "consumer_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING "id" [["uuid", "47d43976-e9a9-49d4-a722-22c62821d3b4"], ["gender", 1], ["birthdate", "1998-09-11 00:00:00"], ["profession", "Global Sales Engineer"], ["insta_user_name", "jeannetta.harber"], ["consumer_id", 1], ["created_at", "2020-04-20 07:49:22.049803"], ["updated_at", "2020-04-20 07:49:22.049803"]]
(0.2ms) RELEASE SAVEPOINT active_record_1
(0.2ms) SAVEPOINT active_record_1
Invitation Create (12.8ms) INSERT INTO "invitations" ("guest_id", "event_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["guest_id", 1], ["event_id", 1], ["created_at", "2020-04-20 07:49:22.071668"], ["updated_at", "2020-04-20 07:49:22.071668"]]
Event Update All (0.5ms) UPDATE "events" SET "invitations_count" = COALESCE("invitations_count", 0) + $1 WHERE "events"."id" = $2 [["invitations_count", 1], ["id", 1]]
(0.2ms) RELEASE SAVEPOINT active_record_1
Invitation Load (0.5ms) SELECT "invitations".* FROM "invitations" WHERE "invitations"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Invitation Load (1.2ms) SELECT "invitations".* FROM "invitations" WHERE "invitations"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Invitation Load (0.3ms) SELECT "invitations".* FROM "invitations" WHERE "invitations"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
(3.3ms) SAVEPOINT active_record_1
Invitation Load (0.9ms) SELECT "invitations".* FROM "invitations" WHERE "invitations"."id" = $1 LIMIT $2 FOR UPDATE [["id", 1], ["LIMIT", 1]]
Guest Load (0.4ms) SELECT "guests".* FROM "guests" WHERE "guests"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Event Load (0.4ms) SELECT "events".* FROM "events" WHERE "events"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Invitation Update (0.7ms) UPDATE "invitations" SET "updated_at" = $1, "notification_statuses" = $2 WHERE "invitations"."id" = $3 [["updated_at", "2020-04-20 07:49:22.111406"], ["notification_statuses", "{\"emails\":[{\"created_at\":\"2020-04-20T07:49:22.105Z\"}]}"], ["id", 1]]
(0.2ms) RELEASE SAVEPOINT active_record_1
Invitation Load (0.4ms) SELECT "invitations".* FROM "invitations" WHERE "invitations"."id" = $1 LIMIT $2 FOR UPDATE [["id", 1], ["LIMIT", 1]]
Invitation Load (0.3ms) SELECT "invitations".* FROM "invitations" WHERE "invitations"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
(0.2ms) SAVEPOINT active_record_1
Invitation Load (1.1ms) SELECT "invitations".* FROM "invitations" WHERE "invitations"."id" = $1 LIMIT $2 FOR UPDATE [["id", 1], ["LIMIT", 1]]
Guest Load (0.9ms) SELECT "guests".* FROM "guests" WHERE "guests"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Event Load (0.3ms) SELECT "events".* FROM "events" WHERE "events"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Invitation Update (0.7ms) UPDATE "invitations" SET "updated_at" = $1, "notification_statuses" = $2 WHERE "invitations"."id" = $3 [["updated_at", "2020-04-20 07:49:22.129222"], ["notification_statuses", "{\"emails\":[{\"created_at\":\"2020-04-20T07:49:22.105Z\"},{\"created_at\":\"2020-04-20T07:49:22.124Z\"}]}"], ["id", 1]]
(0.2ms) RELEASE SAVEPOINT active_record_1
Guest Load (0.3ms) SELECT "guests".* FROM "guests" WHERE "guests"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Invitation Load (1.1ms) SELECT "invitations".* FROM "invitations" WHERE "invitations"."id" = $1 LIMIT $2 FOR UPDATE [["id", 1], ["LIMIT", 1]]
(2.1ms) SAVEPOINT active_record_1
Invitation Update (2.7ms) UPDATE "invitations" SET "updated_at" = $1, "notification_statuses" = $2 WHERE "invitations"."id" = $3 [["updated_at", "2020-04-20 07:49:22.136369"], ["notification_statuses", "{\"emails\":[{\"created_at\":\"2020-04-20T07:49:22.105Z\"},{\"created_at\":\"2020-04-20T07:49:22.124Z\"},{\"created_at\":\"2020-04-20T07:49:22.135Z\"}]}"], ["id", 1]]
(0.5ms) RELEASE SAVEPOINT active_record_1
Invitation Load (4.1ms) SELECT "invitations".* FROM "invitations" WHERE "invitations"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
(1.0ms) ROLLBACK
(0.3ms) BEGIN
(3.4ms) ALTER TABLE "tags" DISABLE TRIGGER ALL;ALTER TABLE "schema_migrations" DISABLE TRIGGER ALL;ALTER TABLE "ar_internal_metadata" DISABLE TRIGGER ALL;ALTER TABLE "areas_establishments" DISABLE TRIGGER ALL;ALTER TABLE "consumer_ratings" DISABLE TRIGGER ALL;ALTER TABLE "addresses" DISABLE TRIGGER ALL;ALTER TABLE "oauth_access_tokens" DISABLE TRIGGER ALL;ALTER TABLE "guests" DISABLE TRIGGER ALL;ALTER TABLE "areas_users" DISABLE TRIGGER ALL;ALTER TABLE "active_storage_blobs" DISABLE TRIGGER ALL;ALTER TABLE "areas" DISABLE TRIGGER ALL;ALTER TABLE "invitations" DISABLE TRIGGER ALL;ALTER TABLE "establishments_managers" DISABLE TRIGGER ALL;ALTER TABLE "consumers" DISABLE TRIGGER ALL;ALTER TABLE "events" DISABLE TRIGGER ALL;ALTER TABLE "taggings" DISABLE TRIGGER ALL;ALTER TABLE "users" DISABLE TRIGGER ALL;ALTER TABLE "oauth_applications" DISABLE TRIGGER ALL;ALTER TABLE "establishments" DISABLE TRIGGER ALL;ALTER TABLE "active_storage_attachments" DISABLE TRIGGER ALL;ALTER TABLE "oauth_access_grants" DISABLE TRIGGER ALL;ALTER TABLE "managers" DISABLE TRIGGER ALL;ALTER TABLE "devices" DISABLE TRIGGER ALL;ALTER TABLE "admins" DISABLE TRIGGER ALL
(5.0ms) COMMIT
(2.3ms) SELECT schemaname || '.' || tablename
FROM pg_tables
WHERE
tablename !~ '_prt_' AND
tablename <> 'schema_migrations' AND tablename <> 'ar_internal_metadata' AND
schemaname = ANY (current_schemas(false))
(1.7ms) select table_name from information_schema.views where table_schema = 'secret_core_test'
(1425.7ms) TRUNCATE TABLE "public"."tags", "public"."areas_establishments", "public"."consumer_ratings", "public"."addresses", "public"."oauth_access_tokens", "public"."guests", "public"."areas_users", "public"."active_storage_blobs", "public"."areas", "public"."invitations", "public"."establishments_managers", "public"."consumers", "public"."events", "public"."taggings", "public"."users", "public"."oauth_applications", "public"."establishments", "public"."active_storage_attachments", "public"."oauth_access_grants", "public"."managers", "public"."devices", "public"."admins" RESTART IDENTITY CASCADE;
(0.5ms) BEGIN
(2.4ms) ALTER TABLE "tags" ENABLE TRIGGER ALL;ALTER TABLE "schema_migrations" ENABLE TRIGGER ALL;ALTER TABLE "ar_internal_metadata" ENABLE TRIGGER ALL;ALTER TABLE "areas_establishments" ENABLE TRIGGER ALL;ALTER TABLE "consumer_ratings" ENABLE TRIGGER ALL;ALTER TABLE "addresses" ENABLE TRIGGER ALL;ALTER TABLE "oauth_access_tokens" ENABLE TRIGGER ALL;ALTER TABLE "guests" ENABLE TRIGGER ALL;ALTER TABLE "areas_users" ENABLE TRIGGER ALL;ALTER TABLE "active_storage_blobs" ENABLE TRIGGER ALL;ALTER TABLE "areas" ENABLE TRIGGER ALL;ALTER TABLE "invitations" ENABLE TRIGGER ALL;ALTER TABLE "establishments_managers" ENABLE TRIGGER ALL;ALTER TABLE "consumers" ENABLE TRIGGER ALL;ALTER TABLE "events" ENABLE TRIGGER ALL;ALTER TABLE "taggings" ENABLE TRIGGER ALL;ALTER TABLE "users" ENABLE TRIGGER ALL;ALTER TABLE "oauth_applications" ENABLE TRIGGER ALL;ALTER TABLE "establishments" ENABLE TRIGGER ALL;ALTER TABLE "active_storage_attachments" ENABLE TRIGGER ALL;ALTER TABLE "oauth_access_grants" ENABLE TRIGGER ALL;ALTER TABLE "managers" ENABLE TRIGGER ALL;ALTER TABLE "devices" ENABLE TRIGGER ALL;ALTER TABLE "admins" ENABLE TRIGGER ALL
(1.8ms) COMMIT