@@ -15,6 +15,7 @@ namespace ServiceControl.RavenDB
1515 using Raven . Client . Documents . Conventions ;
1616 using Raven . Client . ServerWide . Operations ;
1717 using Raven . Embedded ;
18+ using Sparrow . Logging ;
1819
1920 public sealed class EmbeddedDatabase : IDisposable
2021 {
@@ -52,9 +53,20 @@ public static EmbeddedDatabase Start(EmbeddedDatabaseConfiguration databaseConfi
5253
5354 var nugetPackagesPath = Path . Combine ( databaseConfiguration . DbPath , "Packages" , "NuGet" ) ;
5455
56+ LoggingSource . Instance . SetupLogMode (
57+ ( LogMode ) 255 ,
58+ Path . Combine ( databaseConfiguration . LogPath , "Raven.Embedded" ) ,
59+ retentionTime : TimeSpan . FromDays ( 14 ) ,
60+ retentionSize : 1024 * 1024 * 10 ,
61+ compress : false
62+ ) ;
63+
64+ LoggingSource . Instance . EnableConsoleLogging ( ) ;
65+
5566 Logger . InfoFormat ( "Loading RavenDB license from {0}" , licenseFileNameAndServerDirectory . LicenseFileName ) ;
5667 var serverOptions = new ServerOptions
5768 {
69+ GracefulShutdownTimeout = TimeSpan . FromHours ( 1 ) , // During Stop/Dispose we manually control this
5870 CommandLineArgs =
5971 [
6072 $ "--Logs.Mode={ databaseConfiguration . LogsMode } ",
@@ -85,6 +97,7 @@ public static EmbeddedDatabase Start(EmbeddedDatabaseConfiguration databaseConfi
8597
8698 void Start ( ServerOptions serverOptions )
8799 {
100+ this . serverOptions = serverOptions ;
88101 EmbeddedServer . Instance . ServerProcessExited += OnServerProcessExited ;
89102 EmbeddedServer . Instance . StartServer ( serverOptions ) ;
90103
@@ -162,23 +175,72 @@ public async Task<IDocumentStore> Connect(CancellationToken cancellationToken)
162175
163176 public async Task DeleteDatabase ( string dbName )
164177 {
165- using var store = await EmbeddedServer . Instance . GetDocumentStoreAsync ( new DatabaseOptions ( dbName ) { SkipCreatingDatabase = true } ) ;
178+ using var store = await EmbeddedServer . Instance . GetDocumentStoreAsync ( new DatabaseOptions ( dbName )
179+ {
180+ SkipCreatingDatabase = true
181+ } ) ;
166182 await store . Maintenance . Server . SendAsync ( new DeleteDatabasesOperation ( dbName , true ) ) ;
167183 }
168184
185+ public async Task Stop ( CancellationToken cancellationToken )
186+ {
187+ Logger . Debug ( "Stopping RavenDB server" ) ;
188+ EmbeddedServer . Instance . ServerProcessExited -= OnServerProcessExited ;
189+
190+ await shutdownTokenSource . CancelAsync ( ) ;
191+
192+ // TODO: await EmbeddedServer.Instance.StopAsync(cancellationToken);
193+
194+ var processId = await EmbeddedServer . Instance . GetServerProcessIdAsync ( cancellationToken ) ;
195+
196+ var waitForCancellationTask = Task . Delay ( Timeout . Infinite , cancellationToken ) ;
197+ var firstTask = await Task . WhenAny (
198+ Task . Run ( ( ) => EmbeddedServer . Instance . Dispose ( ) , cancellationToken ) ,
199+ waitForCancellationTask
200+ ) ;
201+
202+ if ( firstTask == waitForCancellationTask )
203+ {
204+ try
205+ {
206+ Logger . WarnFormat ( "Killing RavenDB server PID {0} child process because host cancelled" , processId ) ;
207+ var ravenChildProcess = Process . GetProcessById ( processId ) ;
208+ ravenChildProcess . Kill ( entireProcessTree : true ) ;
209+ }
210+ catch ( Exception e )
211+ {
212+ Logger . ErrorFormat ( "Failed to kill RavenDB server PID {0}\n {1}" , processId , e ) ;
213+ }
214+ }
215+
216+ serverOptions = null ! ;
217+ Logger . Debug ( "Stopped RavenDB server" ) ;
218+ }
219+
169220 public void Dispose ( )
170221 {
171222 if ( disposed )
172223 {
173224 return ;
174225 }
175226
176- EmbeddedServer . Instance . ServerProcessExited -= OnServerProcessExited ;
227+ if ( serverOptions != null )
228+ {
229+ EmbeddedServer . Instance . ServerProcessExited -= OnServerProcessExited ;
230+ }
177231
178232 shutdownTokenSource . Cancel ( ) ;
179- Logger . Debug ( "Disposing RavenDB server" ) ;
180- EmbeddedServer . Instance . Dispose ( ) ;
181- Logger . Debug ( "Dispose RavenDB server" ) ;
233+
234+ if ( serverOptions != null )
235+ {
236+ // Set GracefulShutdownTimeout to Zero and exist ASAP, under normal operation instance would already
237+ // have been allowed to gracefully stop during "Stop" method.
238+ serverOptions ! . GracefulShutdownTimeout = TimeSpan . Zero ;
239+ Logger . Debug ( "Disposing RavenDB server" ) ;
240+ EmbeddedServer . Instance . Dispose ( ) ;
241+ Logger . Debug ( "Disposed RavenDB server" ) ;
242+ }
243+
182244 shutdownTokenSource . Dispose ( ) ;
183245 applicationStoppingRegistration . Dispose ( ) ;
184246
@@ -213,6 +275,7 @@ static long DataSize(EmbeddedDatabaseConfiguration configuration)
213275 {
214276 return - 1 ;
215277 }
278+
216279 return info . Length ;
217280 }
218281 catch
@@ -262,6 +325,7 @@ static long DirSize(DirectoryInfo d)
262325 readonly EmbeddedDatabaseConfiguration configuration ;
263326 readonly CancellationToken shutdownCancellationToken ;
264327 readonly CancellationTokenRegistration applicationStoppingRegistration ;
328+ ServerOptions ? serverOptions ;
265329
266330 static TimeSpan delayBetweenRestarts = TimeSpan . FromSeconds ( 60 ) ;
267331 static readonly ILog Logger = LogManager . GetLogger < EmbeddedDatabase > ( ) ;
0 commit comments