Skip to content

Commit 48bb272

Browse files
authored
fix(agdatabase): drop sync state (#94)
* fix(agdatabase): drop sync state
1 parent 23acef6 commit 48bb272

3 files changed

Lines changed: 27 additions & 17 deletions

File tree

src/AgDatabase.cs

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,6 @@ public bool Exists()
8989
/// </summary>
9090
public void Delete()
9191
{
92-
// Deleting the database while it is initializing will leave it in a state where system redo threads are stuck.
93-
// This leaves the database in a state that a SQL Server service restart prior to deletion.
94-
_listener.ForEachAgInstance(WaitForInitialization);
9592
_listener.AvailabilityGroup.Remove(Name);
9693
_listener.ForEachAgInstance(s => s.Database(Name)?.Drop());
9794
}
@@ -156,7 +153,7 @@ public void DropLogin(LoginProperties login)
156153

157154
public void DropAllLogins()
158155
{
159-
foreach(var loginProp in AssociatedLogins()) DropLogin(loginProp);
156+
_listener.ForEachAgInstance(s => s.Database(Name)?.DropAssociatedLogins());
160157
}
161158

162159
public void AddLogin(LoginProperties login)
@@ -187,18 +184,6 @@ public void FullBackup()
187184
_listener.Primary.FullBackup(Name, _backupPathSqlQuery);
188185
}
189186

190-
private void WaitForInitialization(Server server, AvailabilityGroup availabilityGroup)
191-
{
192-
var policy = Policy
193-
.Handle<TimeoutException>()
194-
.WaitAndRetry(4, retryAttempt => TimeSpan.FromMilliseconds(Math.Pow(10, retryAttempt)));
195-
196-
policy.Execute(() => {
197-
if(availabilityGroup.IsInitializing(Name))
198-
throw new TimeoutException($"{server.Name} is initializing. Wait period expired.");
199-
});
200-
}
201-
202187
public void FinalizePrimary()
203188
{
204189
_listener.ForEachAgInstance(FinalizePrimary);

src/SmoFacade/AvailabilityGroup.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,19 @@ public bool IsInitializing(string dbName)
6464
.SingleOrDefault(d => d.Name.Equals(dbName, StringComparison.InvariantCultureIgnoreCase));
6565
if(availabilityDatabase == null)
6666
return false;
67+
6768
availabilityDatabase.Refresh();
6869

69-
return availabilityDatabase.SynchronizationState == MsftSmo.AvailabilityDatabaseSynchronizationState.Initializing;
70+
try {
71+
return availabilityDatabase.SynchronizationState ==
72+
MsftSmo.AvailabilityDatabaseSynchronizationState.Initializing;
73+
}
74+
catch(
75+
MsftSmo.PropertyCannotBeRetrievedException) { } // good here, AvailabilityDatabaseSynchronizationState unavailable means it has no state
76+
catch(MsftSmo.SmoException e) when(e.Message.Contains("Cannot access properties or methods")) { }
77+
catch(Exception) { return true; }
78+
79+
return false;
7080
}
7181
}
7282
}

src/SmoFacade/Database.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,17 @@ public void RestoreWithRecovery()
4040
_database.Refresh();
4141
}
4242

43+
public void DropAssociatedLogins()
44+
{
45+
var logins = Users.Where(u => u.Login != null && u.Login.Name != "sa")
46+
.Select(u => u.Login.Properties());
47+
foreach(var login in logins) {
48+
_server.DropLogin(new LoginProperties() {
49+
Name = login.Name
50+
});
51+
}
52+
}
53+
4354
/// <summary>
4455
/// Kills connections and deletes the database.
4556
/// </summary>
@@ -120,6 +131,10 @@ public void MultiUserMode()
120131

121132
private void ThrowIfUnreadyToDrop()
122133
{
134+
// Deleting the database while it is initializing will leave it in a state where system redo threads are stuck.
135+
// This leaves the database in a state that a SQL Server service restart prior to deletion.
136+
137+
123138
var policyPrep = Policy
124139
.Handle<Exception>()
125140
.WaitAndRetry(3, retryAttempt => TimeSpan.FromMilliseconds(Math.Pow(10, retryAttempt)));

0 commit comments

Comments
 (0)