public async Task CancelQueryBeforeExecutionStartedTest() { // Setup query settings QueryExecutionSettings querySettings = new QueryExecutionSettings { ExecutionPlanOptions = new ExecutionPlanOptions { IncludeActualExecutionPlanXml = false, IncludeEstimatedExecutionPlanXml = true } }; // Create query with a failure callback function ConnectionInfo ci = Common.CreateTestConnectionInfo(null, false, false); ConnectionService.Instance.OwnerToConnectionMap[ci.OwnerUri] = ci; Query query = new Query(Constants.StandardQuery, ci, querySettings, MemoryFileSystem.GetFileStreamFactory()); string errorMessage = null; Query.QueryAsyncErrorEventHandler failureCallback = async(q, e) => { errorMessage = "Error Occured"; }; query.QueryFailed += failureCallback; query.Cancel(); query.Execute(); await query.ExecutionTask; // Validate that query has not been executed but cancelled and query failed called function was called Assert.Equal(true, query.HasCancelled); Assert.Equal(false, query.HasExecuted); Assert.Equal("Error Occured", errorMessage); }
private async Task <EditSession.EditSessionQueryExecutionState> SessionInitializeQueryRunner(string ownerUri, IEventSender eventSender, string query) { // Open a task completion source, effectively creating a synchronous block TaskCompletionSource <EditSession.EditSessionQueryExecutionState> taskCompletion = new TaskCompletionSource <EditSession.EditSessionQueryExecutionState>(); // Setup callback for successful query creation // NOTE: We do not want to set the task completion source, since we will continue executing the query after Func <Query, Task <bool> > queryCreateSuccessCallback = q => Task.FromResult(true); // Setup callback for failed query creation Func <string, Task> queryCreateFailureCallback = m => { taskCompletion.SetResult(new EditSession.EditSessionQueryExecutionState(null, m)); return(Task.FromResult(0)); }; // Setup callback for successful query execution Query.QueryAsyncEventHandler queryCompleteSuccessCallback = q => { taskCompletion.SetResult(new EditSession.EditSessionQueryExecutionState(q)); return(Task.FromResult(0)); }; // Setup callback for failed query execution Query.QueryAsyncErrorEventHandler queryCompleteFailureCallback = (q, e) => { taskCompletion.SetResult(new EditSession.EditSessionQueryExecutionState(null)); return(Task.FromResult(0)); }; // Execute the query ExecuteStringParams executeParams = new ExecuteStringParams { Query = query, GetFullColumnSchema = true, OwnerUri = ownerUri }; await queryExecutionService.InterServiceExecuteQuery(executeParams, null, eventSender, queryCreateSuccessCallback, queryCreateFailureCallback, queryCompleteSuccessCallback, queryCompleteFailureCallback); // Wait for the completion source to complete, this will wait until the query has // completed and sent all its events. return(await taskCompletion.Task); }
private static async Task ExecuteAndCompleteQuery(QueryExecuteParams executeParams, RequestContext <QueryExecuteResult> requestContext, Query query) { // Skip processing if the query is null if (query == null) { return; } // Setup the query completion/failure callbacks Query.QueryAsyncEventHandler callback = async q => { // Send back the results QueryExecuteCompleteParams eventParams = new QueryExecuteCompleteParams { OwnerUri = executeParams.OwnerUri, BatchSummaries = q.BatchSummaries }; await requestContext.SendEvent(QueryExecuteCompleteEvent.Type, eventParams); }; Query.QueryAsyncErrorEventHandler errorCallback = async errorMessage => { // Send back the error message QueryExecuteCompleteParams eventParams = new QueryExecuteCompleteParams { OwnerUri = executeParams.OwnerUri, Message = errorMessage }; await requestContext.SendEvent(QueryExecuteCompleteEvent.Type, eventParams); }; query.QueryCompleted += callback; query.QueryFailed += callback; query.QueryConnectionException += errorCallback; // Launch this as an asynchronous task query.Execute(); // Send back a result showing we were successful await requestContext.SendResult(new QueryExecuteResult { Messages = null }); }
/// <summary> /// Query execution meant to be called from another service. Utilizes callbacks to allow /// custom actions to be taken upon creation of query and failure to create query. /// </summary> /// <param name="executeParams">Parameters for execution</param> /// <param name="connInfo">Connection Info to use; will try and get the connection from owneruri if not provided</param> /// <param name="queryEventSender">Event sender that will send progressive events during execution of the query</param> /// <param name="queryCreateSuccessFunc"> /// Callback for when query has been created successfully. If result is <c>true</c>, query /// will be executed asynchronously. If result is <c>false</c>, query will be disposed. May /// be <c>null</c> /// </param> /// <param name="queryCreateFailFunc"> /// Callback for when query failed to be created successfully. Error message is provided. /// May be <c>null</c>. /// </param> /// <param name="querySuccessFunc"> /// Callback to call when query has completed execution successfully. May be <c>null</c>. /// </param> /// <param name="queryFailureFunc"> /// Callback to call when query has completed execution with errors. May be <c>null</c>. /// </param> public async Task InterServiceExecuteQuery(ExecuteRequestParamsBase executeParams, ConnectionInfo connInfo, IEventSender queryEventSender, Func <Query, Task <bool> > queryCreateSuccessFunc, Func <string, Task> queryCreateFailFunc, Query.QueryAsyncEventHandler querySuccessFunc, Query.QueryAsyncErrorEventHandler queryFailureFunc, bool applyExecutionSettings = false) { Validate.IsNotNull(nameof(executeParams), executeParams); Validate.IsNotNull(nameof(queryEventSender), queryEventSender); Query newQuery; try { // Get a new active query newQuery = CreateQuery(executeParams, connInfo, applyExecutionSettings); if (queryCreateSuccessFunc != null && !await queryCreateSuccessFunc(newQuery)) { // The callback doesn't want us to continue, for some reason // It's ok if we leave the query behind in the active query list, the next call // to execute will replace it. newQuery.Dispose(); return; } } catch (Exception e) { // Call the failure callback if it was provided if (queryCreateFailFunc != null) { await queryCreateFailFunc(e.Message); } return; } // Execute the query asynchronously ExecuteAndCompleteQuery(executeParams.OwnerUri, newQuery, queryEventSender, querySuccessFunc, queryFailureFunc); }
private static void ExecuteAndCompleteQuery(string ownerUri, Query query, IEventSender eventSender, Query.QueryAsyncEventHandler querySuccessCallback, Query.QueryAsyncErrorEventHandler queryFailureCallback) { // Setup the callback to send the complete event Query.QueryAsyncEventHandler completeCallback = async q => { // Send back the results QueryCompleteParams eventParams = new QueryCompleteParams { OwnerUri = ownerUri, BatchSummaries = q.BatchSummaries }; await eventSender.SendEvent(QueryCompleteEvent.Type, eventParams); }; // Setup the callback to send the complete event Query.QueryAsyncErrorEventHandler failureCallback = async(q, e) => { // Send back the results QueryCompleteParams eventParams = new QueryCompleteParams { OwnerUri = ownerUri, BatchSummaries = q.BatchSummaries }; await eventSender.SendEvent(QueryCompleteEvent.Type, eventParams); }; query.QueryCompleted += completeCallback; query.QueryFailed += failureCallback; // Add the callbacks that were provided by the caller // If they're null, that's no problem query.QueryCompleted += querySuccessCallback; query.QueryFailed += queryFailureCallback; // Setup the batch callbacks Batch.BatchAsyncEventHandler batchStartCallback = async b => { BatchEventParams eventParams = new BatchEventParams { BatchSummary = b.Summary, OwnerUri = ownerUri }; await eventSender.SendEvent(BatchStartEvent.Type, eventParams); }; query.BatchStarted += batchStartCallback; Batch.BatchAsyncEventHandler batchCompleteCallback = async b => { BatchEventParams eventParams = new BatchEventParams { BatchSummary = b.Summary, OwnerUri = ownerUri }; await eventSender.SendEvent(BatchCompleteEvent.Type, eventParams); }; query.BatchCompleted += batchCompleteCallback; Batch.BatchAsyncMessageHandler batchMessageCallback = async m => { MessageParams eventParams = new MessageParams { Message = m, OwnerUri = ownerUri }; await eventSender.SendEvent(MessageEvent.Type, eventParams); }; query.BatchMessageSent += batchMessageCallback; // Setup the ResultSet completion callback ResultSet.ResultSetAsyncEventHandler resultCallback = async r => { ResultSetEventParams eventParams = new ResultSetEventParams { ResultSetSummary = r.Summary, OwnerUri = ownerUri }; await eventSender.SendEvent(ResultSetCompleteEvent.Type, eventParams); }; query.ResultSetCompleted += resultCallback; // Launch this as an asynchronous task query.Execute(); }
/// <summary> /// Handles a request to execute a string and return the result /// </summary> internal async Task HandleSimpleExecuteRequest(SimpleExecuteParams executeParams, RequestContext <SimpleExecuteResult> requestContext) { try { string randomUri = Guid.NewGuid().ToString(); ExecuteStringParams executeStringParams = new ExecuteStringParams { Query = executeParams.QueryString, // generate guid as the owner uri to make sure every query is unique OwnerUri = randomUri }; // get connection ConnectionInfo connInfo; if (!ConnectionService.TryFindConnection(executeParams.OwnerUri, out connInfo)) { await requestContext.SendError(SR.QueryServiceQueryInvalidOwnerUri); return; } ConnectParams connectParams = new ConnectParams { OwnerUri = randomUri, Connection = connInfo.ConnectionDetails, Type = ConnectionType.Default }; Task workTask = Task.Run(async() => { await ConnectionService.Connect(connectParams); ConnectionInfo newConn; ConnectionService.TryFindConnection(randomUri, out newConn); Func <string, Task> queryCreateFailureAction = message => requestContext.SendError(message); ResultOnlyContext <SimpleExecuteResult> newContext = new ResultOnlyContext <SimpleExecuteResult>(requestContext); // handle sending event back when the query completes Query.QueryAsyncEventHandler queryComplete = async query => { try { // check to make sure any results were recieved if (query.Batches.Length == 0 || query.Batches[0].ResultSets.Count == 0) { await requestContext.SendError(SR.QueryServiceResultSetHasNoResults); return; } long rowCount = query.Batches[0].ResultSets[0].RowCount; // check to make sure there is a safe amount of rows to load into memory if (rowCount > Int32.MaxValue) { await requestContext.SendError(SR.QueryServiceResultSetTooLarge); return; } SimpleExecuteResult result = new SimpleExecuteResult { RowCount = rowCount, ColumnInfo = query.Batches[0].ResultSets[0].Columns, Rows = new DbCellValue[0][] }; if (rowCount > 0) { SubsetParams subsetRequestParams = new SubsetParams { OwnerUri = randomUri, BatchIndex = 0, ResultSetIndex = 0, RowsStartIndex = 0, RowsCount = Convert.ToInt32(rowCount) }; // get the data to send back ResultSetSubset subset = await InterServiceResultSubset(subsetRequestParams); result.Rows = subset.Rows; } await requestContext.SendResult(result); } finally { Query removedQuery; Task removedTask; // remove the active query since we are done with it ActiveQueries.TryRemove(randomUri, out removedQuery); ActiveSimpleExecuteRequests.TryRemove(randomUri, out removedTask); ConnectionService.Disconnect(new DisconnectParams() { OwnerUri = randomUri, Type = null }); } }; // handle sending error back when query fails Query.QueryAsyncErrorEventHandler queryFail = async(q, e) => { await requestContext.SendError(e); }; await InterServiceExecuteQuery(executeStringParams, newConn, newContext, null, queryCreateFailureAction, queryComplete, queryFail); }); ActiveSimpleExecuteRequests.TryAdd(randomUri, workTask); } catch (Exception ex) { await requestContext.SendError(ex.ToString()); } }
private static void ExecuteAndCompleteQuery(string ownerUri, Query query, IEventSender eventSender, Query.QueryAsyncEventHandler querySuccessCallback, Query.QueryAsyncErrorEventHandler queryFailureCallback) { // Setup the callback to send the complete event Query.QueryAsyncEventHandler completeCallback = async q => { // Send back the results QueryCompleteParams eventParams = new QueryCompleteParams { OwnerUri = ownerUri, BatchSummaries = q.BatchSummaries }; Logger.Write(TraceEventType.Information, $"Query:'{ownerUri}' completed"); await eventSender.SendEvent(QueryCompleteEvent.Type, eventParams); }; // Setup the callback to send the failure event Query.QueryAsyncErrorEventHandler failureCallback = async(q, e) => { // Send back the results QueryCompleteParams eventParams = new QueryCompleteParams { OwnerUri = ownerUri, BatchSummaries = q.BatchSummaries }; Logger.Write(TraceEventType.Error, $"Query:'{ownerUri}' failed"); await eventSender.SendEvent(QueryCompleteEvent.Type, eventParams); }; query.QueryCompleted += completeCallback; query.QueryFailed += failureCallback; // Add the callbacks that were provided by the caller // If they're null, that's no problem query.QueryCompleted += querySuccessCallback; query.QueryFailed += queryFailureCallback; // Setup the batch callbacks Batch.BatchAsyncEventHandler batchStartCallback = async b => { BatchEventParams eventParams = new BatchEventParams { BatchSummary = b.Summary, OwnerUri = ownerUri }; Logger.Write(TraceEventType.Information, $"Batch:'{b.Summary}' on Query:'{ownerUri}' started"); await eventSender.SendEvent(BatchStartEvent.Type, eventParams); }; query.BatchStarted += batchStartCallback; Batch.BatchAsyncEventHandler batchCompleteCallback = async b => { BatchEventParams eventParams = new BatchEventParams { BatchSummary = b.Summary, OwnerUri = ownerUri }; Logger.Write(TraceEventType.Information, $"Batch:'{b.Summary}' on Query:'{ownerUri}' completed"); await eventSender.SendEvent(BatchCompleteEvent.Type, eventParams); }; query.BatchCompleted += batchCompleteCallback; Batch.BatchAsyncMessageHandler batchMessageCallback = async m => { MessageParams eventParams = new MessageParams { Message = m, OwnerUri = ownerUri }; Logger.Write(TraceEventType.Information, $"Message generated on Query:'{ownerUri}' :'{m}'"); await eventSender.SendEvent(MessageEvent.Type, eventParams); }; query.BatchMessageSent += batchMessageCallback; // Setup the ResultSet available callback ResultSet.ResultSetAsyncEventHandler resultAvailableCallback = async r => { ResultSetAvailableEventParams eventParams = new ResultSetAvailableEventParams { ResultSetSummary = r.Summary, OwnerUri = ownerUri }; Logger.Write(TraceEventType.Information, $"Result:'{r.Summary} on Query:'{ownerUri}' is available"); await eventSender.SendEvent(ResultSetAvailableEvent.Type, eventParams); }; query.ResultSetAvailable += resultAvailableCallback; // Setup the ResultSet updated callback ResultSet.ResultSetAsyncEventHandler resultUpdatedCallback = async r => { ResultSetUpdatedEventParams eventParams = new ResultSetUpdatedEventParams { ResultSetSummary = r.Summary, OwnerUri = ownerUri }; Logger.Write(TraceEventType.Information, $"Result:'{r.Summary} on Query:'{ownerUri}' is updated with additional rows"); await eventSender.SendEvent(ResultSetUpdatedEvent.Type, eventParams); }; query.ResultSetUpdated += resultUpdatedCallback; // Setup the ResultSet completion callback ResultSet.ResultSetAsyncEventHandler resultCompleteCallback = async r => { ResultSetCompleteEventParams eventParams = new ResultSetCompleteEventParams { ResultSetSummary = r.Summary, OwnerUri = ownerUri }; Logger.Write(TraceEventType.Information, $"Result:'{r.Summary} on Query:'{ownerUri}' is complete"); await eventSender.SendEvent(ResultSetCompleteEvent.Type, eventParams); }; query.ResultSetCompleted += resultCompleteCallback; // Launch this as an asynchronous task query.Execute(); }
private static async Task ExecuteAndCompleteQuery(QueryExecuteParams executeParams, RequestContext <QueryExecuteResult> requestContext, Query query) { // Skip processing if the query is null if (query == null) { return; } // Setup the query completion/failure callbacks Query.QueryAsyncEventHandler callback = async q => { // Send back the results QueryExecuteCompleteParams eventParams = new QueryExecuteCompleteParams { OwnerUri = executeParams.OwnerUri, BatchSummaries = q.BatchSummaries }; await requestContext.SendEvent(QueryExecuteCompleteEvent.Type, eventParams); }; Query.QueryAsyncErrorEventHandler errorCallback = async errorMessage => { // Send back the error message QueryExecuteCompleteParams eventParams = new QueryExecuteCompleteParams { OwnerUri = executeParams.OwnerUri, Message = errorMessage }; await requestContext.SendEvent(QueryExecuteCompleteEvent.Type, eventParams); }; query.QueryCompleted += callback; query.QueryFailed += callback; query.QueryConnectionException += errorCallback; // Setup the batch callbacks Batch.BatchAsyncEventHandler batchStartCallback = async b => { QueryExecuteBatchNotificationParams eventParams = new QueryExecuteBatchNotificationParams { BatchSummary = b.Summary, OwnerUri = executeParams.OwnerUri }; await requestContext.SendEvent(QueryExecuteBatchStartEvent.Type, eventParams); }; query.BatchStarted += batchStartCallback; Batch.BatchAsyncEventHandler batchCompleteCallback = async b => { QueryExecuteBatchNotificationParams eventParams = new QueryExecuteBatchNotificationParams { BatchSummary = b.Summary, OwnerUri = executeParams.OwnerUri }; await requestContext.SendEvent(QueryExecuteBatchCompleteEvent.Type, eventParams); }; query.BatchCompleted += batchCompleteCallback; // Setup the ResultSet completion callback ResultSet.ResultSetAsyncEventHandler resultCallback = async r => { QueryExecuteResultSetCompleteParams eventParams = new QueryExecuteResultSetCompleteParams { ResultSetSummary = r.Summary, OwnerUri = executeParams.OwnerUri }; await requestContext.SendEvent(QueryExecuteResultSetCompleteEvent.Type, eventParams); }; query.ResultSetCompleted += resultCallback; // Launch this as an asynchronous task query.Execute(); // Send back a result showing we were successful string messages = null; if (query.Batches.Length == 0) { // If there were no batches to execute, send back an informational message that the commands were completed successfully messages = SR.QueryServiceCompletedSuccessfully; } await requestContext.SendResult(new QueryExecuteResult { Messages = messages }); }
/// <summary> /// Handles a request to execute a string and return the result /// </summary> internal Task HandleSimpleExecuteRequest(SimpleExecuteParams executeParams, RequestContext <SimpleExecuteResult> requestContext) { ExecuteStringParams executeStringParams = new ExecuteStringParams { Query = executeParams.QueryString, // generate guid as the owner uri to make sure every query is unique OwnerUri = Guid.NewGuid().ToString() }; // get connection ConnectionInfo connInfo; if (!ConnectionService.TryFindConnection(executeParams.OwnerUri, out connInfo)) { return(requestContext.SendError(SR.QueryServiceQueryInvalidOwnerUri)); } if (connInfo.ConnectionDetails.MultipleActiveResultSets == null || connInfo.ConnectionDetails.MultipleActiveResultSets == false) { // if multipleActive result sets is not allowed, don't specific a connection and make the ownerURI the true owneruri connInfo = null; executeStringParams.OwnerUri = executeParams.OwnerUri; } Func <string, Task> queryCreateFailureAction = message => requestContext.SendError(message); ResultOnlyContext <SimpleExecuteResult> newContext = new ResultOnlyContext <SimpleExecuteResult>(requestContext); // handle sending event back when the query completes Query.QueryAsyncEventHandler queryComplete = async q => { Query removedQuery; // check to make sure any results were recieved if (q.Batches.Length == 0 || q.Batches[0].ResultSets.Count == 0) { await requestContext.SendError(SR.QueryServiceResultSetHasNoResults); ActiveQueries.TryRemove(executeStringParams.OwnerUri, out removedQuery); return; } var rowCount = q.Batches[0].ResultSets[0].RowCount; // check to make sure there is a safe amount of rows to load into memory if (rowCount > Int32.MaxValue) { await requestContext.SendError(SR.QueryServiceResultSetTooLarge); ActiveQueries.TryRemove(executeStringParams.OwnerUri, out removedQuery); return; } SubsetParams subsetRequestParams = new SubsetParams { OwnerUri = executeStringParams.OwnerUri, BatchIndex = 0, ResultSetIndex = 0, RowsStartIndex = 0, RowsCount = Convert.ToInt32(rowCount) }; // get the data to send back ResultSetSubset subset = await InterServiceResultSubset(subsetRequestParams); SimpleExecuteResult result = new SimpleExecuteResult { RowCount = q.Batches[0].ResultSets[0].RowCount, ColumnInfo = q.Batches[0].ResultSets[0].Columns, Rows = subset.Rows }; await requestContext.SendResult(result); // remove the active query since we are done with it ActiveQueries.TryRemove(executeStringParams.OwnerUri, out removedQuery); }; // handle sending error back when query fails Query.QueryAsyncErrorEventHandler queryFail = async(q, e) => { await requestContext.SendError(e); }; return(InterServiceExecuteQuery(executeStringParams, connInfo, newContext, null, queryCreateFailureAction, queryComplete, queryFail)); }