private void DoTaskAsync(ICompileable task, CohortIdentificationTaskExecution execution, int timeout, bool cacheOnCompletion = false) { try { task.Timeout = timeout; task.State = CompilationState.Executing; var accessPoints = task.GetDataAccessPoints(); execution.GetCohortAsync(accessPoints, timeout); task.FinalRowCount = execution.Identifiers.Rows.Count; if (execution.CumulativeIdentifiers != null) { task.CumulativeRowCount = execution.CumulativeIdentifiers.Rows.Count; } task.State = CompilationState.Finished; task.Stopwatch.Stop(); if (cacheOnCompletion) { CacheSingleTask(task); } } catch (Exception ex) { task.Stopwatch.Stop(); task.State = CompilationState.Crashed; task.CrashMessage = ex; } }
private void KickOff(ICompileable task, CohortIdentificationTaskExecution execution, int timeout, bool cacheOnCompletion) { task.State = CompilationState.Scheduled; task.Stopwatch = new Stopwatch(); task.Stopwatch.Start(); var t = new Thread(() => DoTaskAsync(task, execution, timeout, cacheOnCompletion)); Threads.Add(t); t.Start(); }
/// <summary> /// Adds the given AggregateConfiguration, CohortAggregateContainer or JoinableCohortAggregateConfiguration to the compiler Task list or returns the existing /// ICompileable if it is already part of the Compilation list. This will not start the task, you will have to call Launch... to start the ICompileable executing /// </summary> /// <param name="runnable">An AggregateConfiguration, CohortAggregateContainer or JoinableCohortAggregateConfiguration you want to schedule for execution</param> /// <param name="globals"></param> /// <returns></returns> public ICompileable AddTask(IMapsDirectlyToDatabaseTable runnable, IEnumerable <ISqlParameter> globals) { var aggregate = runnable as AggregateConfiguration; var container = runnable as CohortAggregateContainer; var joinable = runnable as JoinableCohortAggregateConfiguration; if (aggregate == null && container == null && joinable == null) { throw new NotSupportedException( "Expected c to be either AggregateConfiguration or CohortAggregateContainer but it was " + runnable.GetType().Name); } CancellationTokenSource source = new CancellationTokenSource(); ICompileable task; //thing that will produce the SQL CohortQueryBuilder queryBuilder; CohortQueryBuilder cumulativeQueryBuilder = null; CohortAggregateContainer parent; //if it is an aggregate if (aggregate != null) { //which has a parent task = new AggregationTask(aggregate, this); queryBuilder = new CohortQueryBuilder(aggregate, globals); parent = aggregate.GetCohortAggregateContainerIfAny(); } else if (joinable != null) { task = new JoinableTask(joinable, this); queryBuilder = new CohortQueryBuilder(joinable.AggregateConfiguration, globals, true); parent = null; } else { task = new AggregationContainerTask(container, this); queryBuilder = new CohortQueryBuilder(container, globals); parent = container.GetParentContainerIfAny(); } //if there is a parent if (parent != null) { //tell the task what the container is for UI purposes really bool isFirstInContainer = parent.GetOrderedContents().First().Equals(runnable); task.SetKnownContainer(parent, isFirstInContainer); //but... //if the container/aggregate being processed isn't the first component in the container if (!isFirstInContainer && IncludeCumulativeTotals) //and we want cumulative totals { cumulativeQueryBuilder = new CohortQueryBuilder(parent, globals); cumulativeQueryBuilder.StopContainerWhenYouReach = (IOrderable)runnable; } } ExternalDatabaseServer cacheServer = null; //if the overall owner has a cache configured if (CohortIdentificationConfiguration.QueryCachingServer_ID != null) { cacheServer = CohortIdentificationConfiguration.QueryCachingServer; queryBuilder.CacheServer = cacheServer; if (cumulativeQueryBuilder != null) { cumulativeQueryBuilder.CacheServer = cacheServer; } } //setup cancellation task.CancellationToken = source.Token; string newsql = ""; string cumulativeSql = ""; try { //get the count(*) SQL newsql = queryBuilder.SQL; if (cumulativeQueryBuilder != null) { cumulativeSql = cumulativeQueryBuilder.SQL; } } catch (QueryBuildingException e) { //it was not possible to generate valid SQL for the task task.CrashMessage = e; task.State = CompilationState.Crashed; } //we have seen this entity before (by ID & entity type) KeyValuePair <ICompileable, CohortIdentificationTaskExecution> existingTask; if (joinable != null) { existingTask = Tasks.SingleOrDefault((kvp => kvp.Key.Child.Equals(joinable))); } else if (aggregate != null) { existingTask = Tasks.SingleOrDefault(kvp => kvp.Key.Child.Equals(aggregate)); } else { existingTask = Tasks.SingleOrDefault(kvp => kvp.Key.Child.Equals(container)); } //job already exists (this is the same as saying existingTask!=null) if (!existingTask.Equals(default(KeyValuePair <ICompileable, CohortIdentificationTaskExecution>))) { if (existingTask.Value.CountSQL.Equals(newsql)) { //The SQl is the same but the order or cached if (existingTask.Key.Order != task.Order)//do not delete this if statement, it prevents rewrites to the database where Order asignment has side affects { existingTask.Key.Order = task.Order; } return(existingTask.Key); //existing task has the same SQL } else { //it is different so cancel the old one existingTask.Value.Cancel(); //throw away the old task Tasks.Remove(existingTask.Key); //dispose of any resources it's holding onto existingTask.Value.Dispose(); } } var isResultsForRootContainer = container != null && container.ID == CohortIdentificationConfiguration.RootCohortAggregateContainer_ID; var taskExecution = new CohortIdentificationTaskExecution(cacheServer, newsql, cumulativeSql, source, queryBuilder.CountOfSubQueries, queryBuilder.CountOfCachedSubQueries, isResultsForRootContainer); //create a new task Tasks.Add(task, taskExecution); return(task); }