The SP1 release of Project Financial Server 2010 includes new features related to custom fields. First of all, the six default custom fields which store the totals for a project are automatically updated whenever the values for the project change. Secondly, the new custom field builder feature allows users to create Project Server custom fields mapped to Project Financial Server 2010 time-phased cost and benefits data.
In order to update the custom fields whenever the project values change, Project Financial Server trigger a summary publish for the project which results in a new job being added to the Project Server Queue. If the project instance is read using any method from the Project Web Service, except for ReadProjectStatus, and the project has pending queue jobs waiting for processing, a ProjectHasWriteLock error is returned. Even if you do not explicitly read the project instance, if you try to update financial values on the same project before all the queue jobs are processed, you will receive the same error.
To make sure all the queue jobs for a project are processed, before reading the project instance you should implement in your code a methods that waits for the Project Server Queue to finish processing. The ReadProjectJobStatus method of the QueueSystem Web Service can be used to determine the queue job status for a project.
private static void WaitForProjectServerQueue(Guid projectUid)
{
const int maxWaitTime = 60; //how many seconds to wait in total for the queue
const int waitStep = 2; //how many seconds to wait each time
int elapsedWaitTime = 0; //how many seconds we have waited for the queue SvcQueueSystem.QueueMsgType[] queueMsgTypes = new SvcQueueSystem.QueueMsgType[] { SvcQueueSystem.QueueMsgType.ProjectUpdate, SvcQueueSystem.QueueMsgType.ProjectCheckIn, SvcQueueSystem.QueueMsgType.ProjectPublish, SvcQueueSystem.QueueMsgType.ProjectPublishSummary }; SvcQueueSystem.JobState[] jobStates = new SvcQueueSystem.JobState[] { SvcQueueSystem.JobState.Processing, SvcQueueSystem.JobState.ReadyForProcessing }; DateTime fromDate = DateTime.Now.AddDays(-1); DateTime toDate = DateTime.Now.AddDays(1);
while (true) { if (elapsedWaitTime >= maxWaitTime) throw new Exception(String.Format("Timeout while waiting for the PS queue to "+ "process pending jobs for project '{0}'", projectUid)); SvcQueueSystem.QueueStatusDataSet dsQueue = queueSystemClient.ReadProjectJobStatus( new Guid[] { projectUid }, queueMsgTypes, jobStates, fromDate, toDate, -1, true, SvcQueueSystem.SortColumn.Undefined, SvcQueueSystem.SortOrder.Undefined);
if (dsQueue.Status.Count() == 0) break; Thread.Sleep(waitStep); elapsedWaitTime += waitStep; }
}
What do you think?
Hello,
A couple of minor but important corrections.
1. There is not reference in your code to the definition of “queueSystemClient”
You have to declare it as follows SvcQueueSystem.QueueSystem queueSystemClient = new SvcQueueSystem.QueueSystem();
2. dsQueue.Status.Count() does not use “()” since is a property
Thanks for your contribution!!
And say hello to my UMT friends Oscar de Lucio and Mauro Angelino.
Daniel Villacis