Skip to content

Draft: Fix timestamp updates for the Arkose custom attributes

What does this MR do and why?

We added the Arkose custom attributes in the MR !84394 (merged), and we opted to use upsert_all for performance reasons.

However, in the current rails version used by GitLab, the timestamps attribute are not handled automatically by upsert_all. In our first iteration, we updated the created_at every time we upsert the custom attributes.

This Merge Request adds a database default value for the created_at attribute. With a default value at the database level, we ensure the created_at is not null when we insert the custom attribute, and we can omit the created_at when we update the custom attributes.

Unfortunately, the created_at and updated_at will have a slightly different timestamp in the insert with this approach.

This difference can be fixed when we moved to Rails 7 because it offers the option to set the timestamps automatically.

Screenshots or screen recordings

These are strongly recommended to assist reviewers and reduce the time to merge your change.

How to set up and validate locally

Numbered steps to set up and validate the change are strongly suggested.

  1. Go to rails console
rails c
  1. Update the failed_attempts to ensure the Arkose integration will be triggered
= User.last
  User Load (1.3ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT 1 /*application:console,db_config_name:main,line:(pry):30:in `__pry__'*/
=> #<User id:104 @new_user2>
[31] pry(main)> user.failed_attempts = 4
=> 4
[32] pry(main)> user.save!
  1. Go to the login page and sign-in

  2. Go back to the Rails console and check the custom attributes created_at and updated_at


[10] pry(main)> user.custom_attributes.reload
  UserCustomAttribute Load (1.2ms)  SELECT "user_custom_attributes".* FROM "user_custom_attributes" WHERE "user_custom_attributes"."user_id" = 104 /*application:console,db_config_name:main,line:(pry):10:in `__pry__'*/
=> [#<UserCustomAttribute:0x00007fc3f8dce1f0
  id: 56,
  created_at: Wed, 13 Apr 2022 19:42:49.232268000 UTC +00:00,
  updated_at: Wed, 13 Apr 2022 19:42:49.222981000 UTC +00:00,
  user_id: 104,
  key: "[FILTERED]",
  value: "566625727b2716444.6251630301">,
 #<UserCustomAttribute:0x00007fc3f8dce088
  id: 57,
  created_at: Wed, 13 Apr 2022 19:42:49.232268000 UTC +00:00,
  updated_at: Wed, 13 Apr 2022 19:42:49.223395000 UTC +00:00,
  user_id: 104,
  key: "[FILTERED]",
  value: "Low">,
 #<UserCustomAttribute:0x00007fc3f8dcdf20 id: 58, created_at: Wed, 13 Apr 2022 19:42:49.232268000 UTC +00:00, updated_at: Wed, 13 Apr 2022 19:42:49.223670000 UTC +00:00, user_id: 104, key: "[FILTERED]", value: "0">,
 #<UserCustomAttribute:0x00007fc3f8dcddb8 id: 59, created_at: Wed, 13 Apr 2022 19:42:49.232268000 UTC +00:00, updated_at: Wed, 13 Apr 2022 19:42:49.223938000 UTC +00:00, user_id: 104, key: "[FILTERED]", value: "0">]
[11] pry(main)> UserCustomAttribute.where(user_id: 104)
  UserCustomAttribute Load (1.7ms)  SELECT "user_custom_attributes".* FROM "user_custom_attributes" WHERE "user_custom_attributes"."user_id" = 104 /*application:console,db_config_name:main,line:bin/rails:4:in `<main>'*/
=> [#<UserCustomAttribute:0x00007fc3eda6f168
  id: 56,
  created_at: Wed, 13 Apr 2022 19:42:49.232268000 UTC +00:00,
  updated_at: Wed, 13 Apr 2022 19:42:49.222981000 UTC +00:00,
  user_id: 104,
  key: "[FILTERED]",
  value: "566625727b2716444.6251630301">,
 #<UserCustomAttribute:0x00007fc3eda6f0a0
  id: 57,
  created_at: Wed, 13 Apr 2022 19:42:49.232268000 UTC +00:00,
  updated_at: Wed, 13 Apr 2022 19:42:49.223395000 UTC +00:00,
  user_id: 104,
  key: "[FILTERED]",
  value: "Low">,
 #<UserCustomAttribute:0x00007fc3eda6efd8 id: 58, created_at: Wed, 13 Apr 2022 19:42:49.232268000 UTC +00:00, updated_at: Wed, 13 Apr 2022 19:42:49.223670000 UTC +00:00, user_id: 104, key: "[FILTERED]", value: "0">,
 #<UserCustomAttribute:0x00007fc3eda6ef10 id: 59, created_at: Wed, 13 Apr 2022 19:42:49.232268000 UTC +00:00, updated_at: Wed, 13 Apr 2022 19:42:49.223938000 UTC +00:00, user_id: 104, key: "[FILTERED]", value: "0">recheck the custom attributesCheck the custom attributes again and verify that the `updated_at` was updated but the `created_at` doesn't.

```ruby
[14] pry(main)> UserCustomAttribute.where(user_id: User.last)
  UserCustomAttribute Load (0.4ms)  SELECT "user_custom_attributes".* FROM "user_custom_attributes" WHERE "user_custom_attributes"."user_id" = 104 /*application:console,db_config_name:main,line:bin/rails:4:in `<main>'*/
=> [#<UserCustomAttribute:0x00007fc3f8ced880
  id: 56,
  created_at: Wed, 13 Apr 2022 19:42:49.232268000 UTC +00:00,
  updated_at: Wed, 13 Apr 2022 19:48:29.325885000 UTC +00:00,
  user_id: 104,
  key: "[FILTERED]",
  value: "24862572907ab3398.5022973601">,
 #<UserCustomAttribute:0x00007fc3f8ced768
  id: 57,
  created_at: Wed, 13 Apr 2022 19:42:49.232268000 UTC +00:00,
  updated_at: Wed, 13 Apr 2022 19:48:29.326378000 UTC +00:00,
  user_id: 104,
  key: "[FILTERED]",
  value: "Low">,
 #<UserCustomAttribute:0x00007fc3f8ced6a0 id: 58, created_at: Wed, 13 Apr 2022 19:42:49.232268000 UTC +00:00, updated_at: Wed, 13 Apr 2022 19:48:29.326686000 UTC +00:00, user_id: 104, key: "[FILTERED]", value: "0">,
 #<UserCustomAttribute:0x00007fc3f8ced5b0 id: 59, created_at: Wed, 13 Apr 2022 19:42:49.232268000 UTC +00:00, updated_at: Wed, 13 Apr 2022 19:48:29.327089000 UTC +00:00, user_id: 104, key: "[FILTERED]", value: "0">]
[15] pry(main)> 

MR acceptanceanalyzed changes encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Marcos Rocha

Merge request reports