Cache the protected tag check
Problem
We already cache protected branches checks, however we don't do that for tags.
Solution
After reviewing Caching guidelines I picked SafeRequestCache
to reduce the number of SQL queries to protected_tags
table. It should trigger only one SQL query to protected_tags
during the request duration. Another option is to cache protected tag names in Redis (as it's done for protected_branches
), but it adds extra load on Redis.
The default Rails SQL cache does not work in this case, because we specify select(:name)
in association.
# Rails cache active
[26] pry(main)> project.protected_tags
D, [2022-05-23T16:44:02.195087 #37353] DEBUG -- : ProtectedTag Load (0.4ms) SELECT "protected_tags".* FROM "protected_tags" WHERE "protected_tags"."project_id" = 59 /*application:console,db_config_name:main,line:bin/rails:4:in `<main>'*/
=> []
[27] pry(main)> project.protected_tags
=> []
# Note: ProtectedTag Load line is missing for the second request, because it was cached.
# Rails cache does not work
[28] pry(main)> project.protected_tags.select(:name)
D, [2022-05-23T16:44:49.488279 #37353] DEBUG -- : ProtectedTag Load (0.4ms) SELECT "protected_tags"."name" FROM "protected_tags" WHERE "protected_tags"."project_id" = 59 /*application:console,db_config_name:main,line:bin/rails:4:in `<main>'*/
=> []
[29] pry(main)> project.protected_tags.select(:name)
D, [2022-05-23T16:44:50.598066 #37353] DEBUG -- : ProtectedTag Load (0.4ms) SELECT "protected_tags"."name" FROM "protected_tags" WHERE "protected_tags"."project_id" = 59 /*application:console,db_config_name:main,line:bin/rails:4:in `<main>'*/
=> []
The lack of cache generates extra N requests to database when we create new tags for mirror updates, for example. We trigger a new request to protected_tags
table for each new tag created.
Edited by Vasilii Iakliushin