PROJECT SERVER 2010. LINEAS BASE HUERFANAS HACEN QUE FALLE EL TRABAJO DE REPORTING (PROJECT PUBLISH).
Buenas,
En este post queríamos haceros llegar la siguiente información, que publicó Brian Smith recientemente en su blog:
Creemos que se trata de un artículo muy bien explicado, y que nos puede pasar en nuestros entornos, así que, aparte de agradecer públicamente a Brian por su excelente artículo, procedemos a traducirlo para la comunidad de Project hispano parlante. Esperamos sinceramente os resulte de utilidad:
“Este problema lleva ocurriendo un tiempo ya, incluso hubo clientes que lo empezaron a sufrir según se lanzó esta versión (Project Server 2010), pero no habíamos sido capaces de conseguir reproducirlo, y entender exactamente qué lo estaba causando. Hemos sido capaces de entenderlo ahora, y tenemos una actualización que lo debe arreglar (saldrá, salvo problemas de última hora, en la actualización acumulativa de Junio de 2012.) Hay varias maneras de trabajar para limitar las probabilidades de que nos ocurra esto, así que hemos decidido compartirlas con vosotros, hasta que se libere la actualización.
Vamos a echar un vistazo primero a los síntomas. El indicador más común de este problema, como el título sugiere, está relacionado con valores de línea base huérfanos, los cuales nos causan el error cuando publicamos un proyecto (Failed but Not blocking Correlation) en el trabajo de “Reporting (Project Publish)” que se genera después de publicar correctamente un proyecto en nuestro sitio PWA. Se nos mostrarán los siguientes errores, si pinchamos en los detalles de cada trabajo fallido en la cola:
ReportingProjectChangeMessageFailed (24006) - The INSERT statement conflicted with the FOREIGN KEY constraint "FK_MSP_EpmTaskBaseline_ProjectUID_TaskUID". The conflict occurred in database "ProjectServer_Reporting", table "dbo.MSP_EpmTask". The statement has been terminated..
GeneralQueueJobFailed (26000) - ReportingProjectPublish.ReportProjectPublishMessageEx
Estos fallos se refieren al trabajo mencionado anteriormente “Reporting (Project Publish)”, lo cual indica que los informes generados a partir de la base de datos de Reporting (y del cubo OLAP, puedan no tener toda la información.)
Existen ocasiones en las que incluso hay fallos al intentar guardar un proyecto, donde se nos muestre el mensaje genérico “MSSOAP 16 Send Incomplete” desde Project PRO 2010 (aunque cuando volvamos a intentar guardarlo pueda hacerlo correctamente), o en el PWA, podamos ver el siguiente mensaje de error:
GeneralQueueException (9131) A Project Operation failed due to a Queue Exception. Sub Job ID is: . Exception details are: System.NullReferenceException: …at Microsoft.Office.Project.DataEdit.Assignments.AssignmentCalendarUpdateHelper.ConvertActualContourToElapsed(,,,
También puede ser que tengamos problemas con usuarios intentando acceder a partes de horas, y se nos muestre un mensaje indicando que no se ha podido cargar la vista, y que pulsemos en OK para recargarla (y aunque pinchemos, no haga nada…)
El error que aparecería en los logs ULS se referiría a un calendario, del cual no puede encontrar el UID…
Exception occurred in method Microsoft.Office.Project.Server.BusinessLayer.Statusing.StatusingGetMyWorkForGridJson System.InvalidOperationException: CacheProjectBaseCalendars could not find project calendar for project. CalUid=0c13de33-2a07-4310-b091-c77990d9dd6a
La causa de todos estos problemas estriba en que cuando usamos alguna de las opciones de guardar y enviar (XML, CSV, Excel, etc) estamos cambiando (de manera incorrecta) algunos de los GUIDs asociados con entidades como las tareas y/o calendarios. Esto no está afectando los GUIDs de las tareas principales y de las asignaciones, ya que estos valores incorrectos no persisten hacia la base de datos, pero sí crean una nueva línea base para aquellos GUIDs nuevos de las tareas no existentes, y pueden también guardar un GUID para un calendario incorrecto (el cual nos lleva al problema de los partes de horas.)
Vamos primero a ver la manera de evitar este problema, y luego veremos cómo detectarlo, y “limpiarlo” a nivel de las bases de datos.
Si necesitamos usar la opción de Guardar y Enviar, la mejor opción mientras se libera la actualización mencionada es la siguiente: guardemos el proyecto, y publiquémoslo, si fuera necesario. Hagamos luego lo que sea pertinente, referente a la opción de Guardar y Enviar, e, inmediatamente después de esto, cerremos y desprotejamos el proyecto, pero no lo volvamos a guardar al sitio PWA. Rechacemos los cambios, si nos preguntara al respecto, (aunque tengamos claro que por supuesto hayamos debido guardarlo antes de usar el Guardar y Enviar) para evitar perder cambios que podamos necesitar. Como los datos “chungos” puedan persistir en la caché local, ésta será una de las raras ocasiones donde os sugeriremos que se elimine dicho proyecto de la caché local, después de habernos asegurado que el proceso de guardar y de desprotección han terminado correctamente.
AVISO. Las siguientes acciones implican consultas directas a las bases de datos de Project Server. Por favor, tengamos claro contra qué base de datos las estamos ejecutando, de tal manera que lo hagamos en las adecuadas. Independientemente, como siempre que hagamos algo de este tipo, recomendamos encarecidamente haber realizado copias de seguridad de las bases de datos antes, por lo que pudiera pasar…
La detección de esta condición es muy directa, ya que estamos buscando líneas base existentes, para una tarea que no existe, de tal manera que la siguiente consulta, ejecutada contra la base de datos de Draft nos localizará dicha información:
USE ProjectServer_Draft -- aquí debemos especificar el nombre adecuado para la base de datos Draft
select PROJ_NAME, MTB.PROJ_UID,TASK_UID,TB_BASE_NUM from MSP_TASK_BASELINES MTB
inner join MSP_PROJECTS MP on MTB.proj_uid=MP.proj_uid
where TASK_UID not in (select TASK_UID from MSP_TASKS)
Si nos devuelve información, indicará que dicha condición existe, a la vez que identificará para cuales proyectos. Esto resulta interesante, de tal manera que se recomienda hacerlos desaparecer de la caché local de los jefes de proyecto, ya que pudieran reintroducir el problema en el futuro.
Los siguientes scripts se encargan de “limpiar” las bases de datos; simplemente eliminan registros de las líneas base de tareas que no existen:
-- Script que se debe ejecutar en la base de datos Draft
USE ProjectServer_Draft -- aquí debemos especificar el nombre adecuado para la base de datos Draft
delete from MSP_TASK_BASELINES where TASK_UID not in (select TASK_UID from MSP_TASKS)
-- Script que se debe ejecutar en la base de datos Published
USE ProjectServer_Published -- aquí debemos especificar el nombre adecuado para la base de datos Publisheddelete from MSP_TASK_BASELINES where TASK_UID not in (select TASK_UID from MSP_TASKS)
Espero esto nos ayude a entender la naturaleza de este problema, y las maneras de evitarlo mientras se haga pública la actualización que lo corrige. Nuestras disculpas por las molestias esto haya podido causar a nuestros clientes, y esperamos que, para aquellos que necesitaran ejecutar los scripts de limpieza de manera periódica, esto les pueda aliviar.
Las entradas de los logs ULS, asociadas a los errores en la cola de Project Server (para optimizar los motores de búsqueda) son las siguientes:
05/01/2012 11:57:55.67 Microsoft.Office.Project.Server (0x1D74) 0x335C Project Server Reporting atwj Critical Standard Information:PSI Entry Point: Project User: REDMOND\brismith Correlation Id: e1f4e953-7dea-448a-a528-709075c698bf PWA Site URL: https://brismith8100/PWA SSP Name: Project Server Service Application PSError: ReportingProjectChangeMessageFailed (24006) RDS: The request to synchronize change(s) to project Project UID='216733b0-e194-469a-afc3-9235da4ce4c1'. PublishType='ProjectPublish' failed. Message: 'ReportingProjectChangeMessageFailed'. Message Body: The INSERT statement conflicted with the FOREIGN KEY constraint "FK_MSP_EpmTaskBaseline_ProjectUID_TaskUID". The conflict occurred in database "ProjectServer_Reporting", table "dbo.MSP_EpmTask". The statement has been terminated. Error:(null) e1f4e953-7dea-448a-a528-709075c698bf
Para el error del parte de horas:
05/01/2012 12:13:29.65 w3wp.exe (0x2444) 0x23D8 Project Server Task Statusing and Updates btw9 High CacheProjectBaseCalendars: could not locate data for calendar 0c13de33-2a07-4310-b091-c77990d9dd6a for project 216733b0-e194-469a-afc3-9235da4ce4c1 e5dd4eaf-551a-469b-a3e0-1f60e2f3d1af
05/01/2012 12:13:29.85 w3wp.exe (0x2444) 0x23D8 Project Server General 0000 Exception Exception occurred in method Microsoft.Office.Project.Server.BusinessLayer.Statusing.StatusingGetMyWorkForGridJson System.InvalidOperationException: CacheProjectBaseCalendars could not find project calendar for project. CalUid=0c13de33-2a07-4310-b091-c77990d9dd6a at Microsoft.Office.Project.Server.BusinessLayer.TimePhasedDataAccess.CacheProjectBaseCalendars() at Microsoft.Office.Project.Server.BusinessLayer.TimePhasedDataAccess..ctor(StatusingPageLoadDataSet dataset) at Microsoft.Office.Project.Server.BusinessLayer.Statusing.ReadStatusTimephasedDataForResource(IList`1 gridChanges, Guid[] vAssnUids, IDictionary`2 assn2proj, StatusingTimephasedPeriod[] tpdPeriods, DateTime tpStart, DateTime tpEnd) at Microsoft.Office.Project.Server.BusinessLayer.Statusing.<>c__DisplayClass57.<CreateTimephasedDataColumnFiller>b__56(IEnumerable`1 Keys) at Microsoft.SharePoint.JSGrid.GridSerializer.BuildOutput() at Microsoft.SharePoint.JSGrid.GridSerializer.ToJson(Serializer s) at Microsoft.SharePoint.JsonUtilities.Serializer.SerializeToJson(Object o) at Microsoft.Office.Project.Server.BusinessLayer.Statusing.GetMyWorkForGridJson(JsGridSerializerArguments gridSerializerArgs, String gridChangesJson, String projectAssignmentsMap, Guid viewUid, String timephasedStart, String timephasedEnd, Byte pane, Int32 durationType, Int32 workType, Int32 dateFormat, Boolean clearPersistedProperties, Nullable`1 rowFilterType) at Microsoft.Office.Project.Server.Wcf.Implementation.PWAImpl.StatusingGetMyWorkForGridJson(JsGridSerializerArguments gridSerializerArgs, String gridChangesJson, String projectAssignmentsMap, Guid viewUid, String timephasedStart, String timephasedEnd, Byte pane, Int32 durationType, Int32 workType, Int32 dateFormat, Boolean clearPersistedProperties, Nullable`1 rowFilterType) e5dd4eaf-551a-469b-a3e0-1f60e2f3d1af
“
Esperamos sinceramente os resulte igual de útil y provechoso que nos ha parecido a nosotros.
Jorge Puig