@@ -3918,10 +3918,76 @@ def up
3918
3918
it "allows re-entrancy" do
3919
3919
migration . safely_acquire_lock_for_table ( table_name ) do
3920
3920
migration . safely_acquire_lock_for_table ( table_name ) do
3921
- expect ( locks_for_table ( table_name , connection : alternate_connection ) ) . not_to be_empty
3921
+ expect ( locks_for_table ( table_name , connection : alternate_connection ) ) . to contain_exactly (
3922
+ having_attributes (
3923
+ table : "bogus_table" ,
3924
+ lock_type : "AccessExclusiveLock" ,
3925
+ granted : true ,
3926
+ pid : kind_of ( Integer ) ,
3927
+ ) ,
3928
+ )
3922
3929
end
3923
- expect ( locks_for_table ( table_name , connection : alternate_connection ) ) . not_to be_empty
3930
+
3931
+ expect ( locks_for_table ( table_name , connection : alternate_connection ) ) . to contain_exactly (
3932
+ having_attributes (
3933
+ table : "bogus_table" ,
3934
+ lock_type : "AccessExclusiveLock" ,
3935
+ granted : true ,
3936
+ pid : kind_of ( Integer ) ,
3937
+ ) ,
3938
+ )
3924
3939
end
3940
+
3941
+ expect ( locks_for_table ( table_name , connection : alternate_connection ) ) . to be_empty
3942
+ end
3943
+
3944
+ it "allows re-entrancy when inner lock is a lower level" do
3945
+ migration . safely_acquire_lock_for_table ( table_name ) do
3946
+ migration . safely_acquire_lock_for_table ( table_name , mode : :exclusive ) do
3947
+ locks_for_table = locks_for_table ( table_name , connection : alternate_connection )
3948
+
3949
+ aggregate_failures do
3950
+ expect ( locks_for_table ) . to contain_exactly (
3951
+ having_attributes (
3952
+ table : "bogus_table" ,
3953
+ lock_type : "AccessExclusiveLock" ,
3954
+ granted : true ,
3955
+ pid : kind_of ( Integer ) ,
3956
+ ) ,
3957
+ having_attributes (
3958
+ table : "bogus_table" ,
3959
+ lock_type : "ExclusiveLock" ,
3960
+ granted : true ,
3961
+ pid : kind_of ( Integer ) ,
3962
+ ) ,
3963
+ )
3964
+
3965
+ expect ( locks_for_table . first . pid ) . to eq ( locks_for_table . last . pid )
3966
+ end
3967
+ end
3968
+
3969
+ locks_for_table = locks_for_table ( table_name , connection : alternate_connection )
3970
+
3971
+ aggregate_failures do
3972
+ expect ( locks_for_table ) . to contain_exactly (
3973
+ having_attributes (
3974
+ table : "bogus_table" ,
3975
+ lock_type : "AccessExclusiveLock" ,
3976
+ granted : true ,
3977
+ pid : kind_of ( Integer ) ,
3978
+ ) ,
3979
+ having_attributes (
3980
+ table : "bogus_table" ,
3981
+ lock_type : "ExclusiveLock" , # Postgres releases the inner lock once the outer lock is released
3982
+ granted : true ,
3983
+ pid : kind_of ( Integer ) ,
3984
+ ) ,
3985
+ )
3986
+
3987
+ expect ( locks_for_table . first . pid ) . to eq ( locks_for_table . last . pid )
3988
+ end
3989
+ end
3990
+
3925
3991
expect ( locks_for_table ( table_name , connection : alternate_connection ) ) . to be_empty
3926
3992
end
3927
3993
@@ -3939,6 +4005,9 @@ def up
3939
4005
"Lock escalation detected! Cannot change lock level from :share to :exclusive for \" public\" .\" bogus_table\" ."
3940
4006
)
3941
4007
4008
+ # the exception above was caught and therefore the parent lock shouldn't be released yet
4009
+ expect ( locks_for_table ( table_name , connection : alternate_connection ) ) . to_not be_empty
4010
+
3942
4011
migration . safely_acquire_lock_for_table ( table_name , mode : :exclusive ) { }
3943
4012
end
3944
4013
end . to raise_error (
0 commit comments