Ejemplo n.º 1
0
        // if work is available to do and another web server in the web farm isn't already doing,
        // this returns a unit of work used to wrap the work.
        public JobUnitOfWork ReserveWork(string workerId, IJob job)
        {
            long?workItemId = null;

            // We do a double check here because this may be the first DB query that runs when starting
            // WebBackgrounder. For those using EF Code First, this could trigger a database creation
            // (typically on a dev box, hopefully not in production). A database can't be created inside
            // a transaction scope so we run this query here first.
            var lastWorkItem = _workItemRepository.GetLastWorkItem(job);

            if (lastWorkItem.IsActive() && !lastWorkItem.IsTimedOut(job, () => DateTime.UtcNow))
            {
                return(null);
            }

            _workItemRepository.RunInTransaction(() =>
            {
                lastWorkItem = _workItemRepository.GetLastWorkItem(job);

                if (lastWorkItem.IsTimedOut(job, () => DateTime.UtcNow))
                {
                    lastWorkItem.Completed = DateTime.UtcNow;
                    _workItemRepository.SetWorkItemFailed(lastWorkItem.Id,
                                                          new TimeoutException("Workitem expired. Job timeout was " + job.TimeOut));
                    lastWorkItem = null;
                }

                if (lastWorkItem.IsActive())
                {
                    workItemId = null;
                    return;
                }
                workItemId = _workItemRepository.CreateWorkItem(workerId, job);
            }
                                                 );

            if (workItemId == null)
            {
                return(null);
            }
            return(new JobUnitOfWork(_workItemRepository, workItemId.Value));
        }