private bool SetupRequestToProperDatabase(IHttpContext ctx) { var requestUrl = ctx.GetRequestUrlForTenantSelection(); var match = databaseQuery.Match(requestUrl); var onBeforeRequest = BeforeRequest; if (match.Success == false) { currentTenantId.Value = Constants.SystemDatabase; currentDatabase.Value = SystemDatabase; currentConfiguration.Value = SystemConfiguration; databaseLastRecentlyUsed.AddOrUpdate("System", SystemTime.UtcNow, (s, time) => SystemTime.UtcNow); if (onBeforeRequest != null) { var args = new BeforeRequestEventArgs { Context = ctx, IgnoreRequest = false, TenantId = "System", Database = SystemDatabase }; onBeforeRequest(this, args); if (args.IgnoreRequest) return false; } return true; } var tenantId = match.Groups[1].Value; Task<DocumentDatabase> resourceStoreTask; bool hasDb; try { hasDb = TryGetOrCreateResourceStore(tenantId, out resourceStoreTask); } catch (Exception e) { OutputDatabaseOpenFailure(ctx, tenantId, e); return false; } if (hasDb) { try { if (resourceStoreTask.Wait(TimeSpan.FromSeconds(30)) == false) { ctx.SetStatusToNotAvailable(); ctx.WriteJson(new { Error = "The database " + tenantId + " is currently being loaded, but after 30 seconds, this request has been aborted. Please try again later, database loading continues.", }); return false; } if (onBeforeRequest != null) { var args = new BeforeRequestEventArgs { Context = ctx, IgnoreRequest = false, TenantId = tenantId, Database = resourceStoreTask.Result }; onBeforeRequest(this, args); if (args.IgnoreRequest) return false; } } catch (Exception e) { OutputDatabaseOpenFailure(ctx, tenantId, e); return false; } var resourceStore = resourceStoreTask.Result; databaseLastRecentlyUsed.AddOrUpdate(tenantId, SystemTime.UtcNow, (s, time) => SystemTime.UtcNow); if (string.IsNullOrEmpty(Configuration.VirtualDirectory) == false && Configuration.VirtualDirectory != "/") { ctx.AdjustUrl(Configuration.VirtualDirectory + match.Value); } else { ctx.AdjustUrl(match.Value); } currentTenantId.Value = tenantId; currentDatabase.Value = resourceStore; currentConfiguration.Value = resourceStore.Configuration; } else { ctx.SetStatusToNotFound(); ctx.WriteJson(new { Error = "Could not find a database named: " + tenantId }); return false; } return true; }
private bool SetupRequestToProperDatabase(IHttpContext ctx) { var requestUrl = ctx.GetRequestUrlForTenantSelection(); var match = databaseQuery.Match(requestUrl); var onBeforeRequest = BeforeRequest; if (match.Success == false) { currentTenantId.Value = Constants.SystemDatabase; currentDatabase.Value = SystemDatabase; currentConfiguration.Value = SystemConfiguration; SystemDatabase.WorkContext.UpdateFoundWork(); if (onBeforeRequest != null) { var args = new BeforeRequestEventArgs { Context = ctx, IgnoreRequest = false, TenantId = "System", Database = SystemDatabase }; onBeforeRequest(this, args); if (args.IgnoreRequest) return false; } return true; } var tenantId = match.Groups[1].Value; Task<DocumentDatabase> resourceStoreTask; bool hasDb; try { hasDb = TryGetOrCreateResourceStore(tenantId, out resourceStoreTask); } catch (Exception e) { OutputDatabaseOpenFailure(ctx, tenantId, e); return false; } if (hasDb) { try { const int timeToWaitForDatabaseToLoad = 5; if (resourceStoreTask.IsCompleted == false && resourceStoreTask.IsFaulted == false) { if (_maxNumberOfThreadsForDatabaseToLoad.Wait(0) == false) { ctx.SetStatusToNotAvailable(); ctx.WriteJson(new { Error = string.Format( "The database {0} is currently being loaded, but there are too many requests waiting for database load. Please try again later, database loading continues.", tenantId), }); return false; } try { if (resourceStoreTask.Wait(TimeSpan.FromSeconds(timeToWaitForDatabaseToLoad)) == false) { ctx.SetStatusToNotAvailable(); ctx.WriteJson(new { Error = string.Format( "The database {0} is currently being loaded, but after {1} seconds, this request has been aborted. Please try again later, database loading continues.", tenantId, timeToWaitForDatabaseToLoad), }); return false; } } finally { _maxNumberOfThreadsForDatabaseToLoad.Release(); } } if (onBeforeRequest != null) { var args = new BeforeRequestEventArgs { Context = ctx, IgnoreRequest = false, TenantId = tenantId, Database = resourceStoreTask.Result }; onBeforeRequest(this, args); if (args.IgnoreRequest) return false; } } catch (Exception e) { OutputDatabaseOpenFailure(ctx, tenantId, e); return false; } var resourceStore = resourceStoreTask.Result; resourceStore.WorkContext.UpdateFoundWork(); if (string.IsNullOrEmpty(Configuration.VirtualDirectory) == false && Configuration.VirtualDirectory != "/") { ctx.AdjustUrl(Configuration.VirtualDirectory + match.Value); } else { ctx.AdjustUrl(match.Value); } currentTenantId.Value = tenantId; currentDatabase.Value = resourceStore; currentConfiguration.Value = resourceStore.Configuration; } else { ctx.SetStatusToNotFound(); ctx.WriteJson(new { Error = "Could not find a database named: " + tenantId }); return false; } return true; }