11module SapiModule
22 module StoredProcedures
33
4+ ##
5+ # This takes several hours to run:
6+ #
7+ # - The first hour is for all the views prior to trade_plus_complete view
8+ # - The remainder of the time is exclusively spent on trade_plus_complete_view
9+ #
10+ # Runtime grows as the database grows, and in particular the trade plus
11+ # dataset is growing quite a bit year on year.
12+
413 def self . rebuild
514 ActiveRecord ::Base . transaction do
6- [
15+ # The names of the functions beginnning 'rebuild_' to be run in sequence
16+ to_rebuild = [
717 :taxonomy ,
818 :cites_accepted_flags ,
919 :listing_changes_mview ,
@@ -24,9 +34,29 @@ def self.rebuild
2434 :trade_shipments_cites_suspensions_mview ,
2535 :non_compliant_shipments_view ,
2636 :trade_plus_complete_mview
27- ] . each { |p |
37+ ]
38+
39+ connection = ActiveRecord ::Base . connection
40+
41+ to_lock = connection . execute (
42+ # This is not great, because it relies on things being called mview
43+ # when they're not matviews, it's the tables we're locking, matviews
44+ # don't respond to LOCK TABLE.
45+ "SELECT relname FROM pg_class WHERE relname LIKE '%_mview' AND relkind = 'r';"
46+ ) . to_a . map { |row | row [ 'relname' ] }
47+
48+ to_lock . each { |relname |
49+ # Lock tables in advance to prevent deadlocks forcing a rollback.
50+ puts "Locking table: #{ relname } "
51+
52+ # We need ACCESS EXCLUSIVE because this is used by DROP TABLE, and
53+ # most of the rebuild_... functions are dropping and recreating the
54+ # matviews.
55+ connection . execute ( "LOCK TABLE #{ relname } IN ACCESS EXCLUSIVE MODE" )
56+ }
57+
58+ to_rebuild . each { |p |
2859 puts "Procedure: #{ p } "
29- connection = ActiveRecord ::Base . connection
3060
3161 # Within the current transaction, set work_mem to a higher-than-usual
3262 # value, so that matviews can be built more efficiently.
0 commit comments