5 июл. 2012 г.

Обновление рабочих процессов

Фактически никакой версионности в рабочих процессах (далее - РП) Visual Studio, в отличие от декларативных РП, не существует. То, что в различных статьях называется обновлением рабочего процесса, по сути представляет из себя копирование и развёртывание ещё одного РП. Так называемая новая версия связана со старой только посредством идентификатора, а названия и имена классов могут различаться. Никаких атрибутов для хранения номера версии в определении РП (workflow template) нет, и пользователь никогда не узнает, какой версией какого процесса он пользуется, если, конечно, разработчик не упомянет версию в названии или описании РП.

Необходимость в организации обновления РП возникает, если разработчик изменил класс РП, добавив туда новые активности, методы, поля и т.д. Если меняется только код методов, например, исправляются ошибки, то достаточно просто обновить решение, чтобы новый код попал в GAC, после этого РП нормально продолжат свою работу.
Если же разработчик изменил структуру РП, то простого обновления сборки в GAC недостаточно, ибо после такого обновления SharePoint не сможет восстановить состояние РП: сохранялась одна структура РП, а при восстановлении она оказывается другой.

Итак, три необходимых условия для осуществления обновления РП:
  1. Разный код для разных версий РП.
  2. Определения разных версий РП должны иметь одинаковый идентификатор.
  3. Определения разных версий РП должны находиться решениях с разными идентификаторами.
Первый принцип можно реализовать по-разному: создать разноименные классы в одной сборке или одноименные классы в разных сборках.
Остальные параметры решения: идентификаторы и названия возможностей, название и описание определения РП и пр. - можно менять или оставить прежними, на обновление это не влияет.

Я решил записать алгоритм одной из возможных реализаций изменения проекта для корректного обновления РП.

Шаг 1. Изменить идентификатор решения. 
В Visual Studio меняем свойства Solution Id у нашего WSP.

Шаг 2. Изменить версию сборки. 
Если версия сборки меняется при каждом билде, то это хорошо. Если же не меняется, то придётся поменять версию сборки вручную, чтобы новая версия работала вместе со старой.

Шаг 3. Добавить старую сборку в решение. 
Кто не знает, как это сделать, может прочитать инструкцию http://msdn.microsoft.com/ru-ru/library/ee231595.
При добавления сборки нужно в поле Location к имени файла добавить название подпапки (получится, например, "V1\MyWorkflow.dll"), потому что Visual Studio не добавит в решение два одноименных файла: старую сборку и текущую.

Шаг 4. Изменить определение РП. 
Этот шаг не обязателен. В атрибуте CodeBesideAssembly обычно указывается переменная $assemblyname$, так что прописывать новую версию сборки не потребуется. Можно изменить атрибут Name, добавив в название РП номер версии, исключительно для информирования пользователей.
Важно, что нельзя менять идентификатор определения - атрибут Id. Определения РП с одинаковым идентификатором, но находящиеся в разных решениях, SharePoint рассматривает как разные версии одного определения и подменяет старую версию новой. Если же определения находятся в одной возможности или в одном решении, то установится только первое.


Повторяясь, напомню, что этот алгоритм не единственно возможный. Хоть во всех статьях об обновлении РП и пишут о необходимости создания новой сборки, наличие этой новой сборки для развёртывания новой версии РП, строго говоря, не обязательно. Конечно, такой вариант грамотней и предпочтительней, но ведь можно пойти другим путём - создать копию класса РП в текущей сборке! Тогда выполнять шаги 2 и 3 не потребуется, а на шаге 4 вместо атрибута CodeBesideAssembly нужно будет поменять атрибут CodeBesideClass. Способ с копированием класса даже проще и быстрее и лучше подходит для ситуации, когда обновилась не только сборка с РП, но ещё десяток-другой связанных сборок, которые придётся копировать вместе со сборкой РП. Или, например, в сборке с РП находятся другие элементы: веб-части, приёмники событий и т.д. - для которых смена версии сборки влечёт необходимость дополнительных действий при обновлении.


Действия при обновлении РП следующие:
  1. Отозвать старое решение.
  2. Развернуть новое.
  3. Активировать возможность.
  4. Обновить существующие ассоциации с РП, включив их, потому что при деактивации старой возможности ассоциации отключаются.

8 комментариев:

  1. Хммм, я делал версионность проца VS без особых проблем. и двух колонок не надо было, и старые процы дорабатывали свою жись, а новые запускались по новой логике и все тип топ...
    Вспоминаю ...
    1. Делаем новый РП и новый! wsp. (как бы старый то пусть живет).
    1.1. Поднимаем версию сборки dll (что бы старичку не мешать)
    1.2. В xml определении проца в названии и описании добавляем инфу об версии - что бы потом было понятно с чем дело имеем.
    1.3 прописываем ссылку на новую сборку.
    1.4 Очень важно: worflow\id, аля guid проца оставляем прежним!!!. - вот как раз из-за этого фокуса происходит подмена старой версии проца на новую, без изменения колонки и т.п.
    2. Все. деплоим. активируем. пере-ассоциируем.

    Примечание:
    1. Возможно я что то пропустил...
    2. Проделывал, этот фокус давно еще под 2007, но не думаю что в 2010 что то координально поменялось.
    3. Минус такого подхода, что старые версии хоть и отработают по старой логике , но создать новые по старой уже не получится.
    4. Следует учесть, что версинность требует не только код, а может потребоваться и другие части РП, например формы задачи, служебные конфиги и т.п.

    PS: как я понимаю, почему это все работает,
    1) при ассоцииации или запуске проца, шарик берет XML определения WF из фичи, и сохраняет в БД, и проц каждый раз как просыпается смотрит именно XML которая в БД, так что старые процы живут по своей логике.
    2) а при запуске нового проца возьмется соответственно новая XML с новыми инструкциями.

    ОтветитьУдалить
    Ответы
    1. Александр, спасибо за комментарий! Попробую такой вариант.

      Удалить
  2. Во, нашел свой протокол бубнов:

    Sharepoint workflow version.
    http://bluesurftech.com/TechBlog/Lists/Posts/Post.aspx?ID=49 (ссылка уже дохлая)
    New Version of Sharepoint workflow using a .wsp Package. This will allow you to create a new version as a fully separate feature.
    [Obsolete]
    1.   Manifest.xml – change SolutionID using New Guid
    2. Manifest.xml-change Destination Location folder to include version number, keep source location folder with no version.
    3. Change Assembly version to next version, Properties, Application, Assembly Information
    4.     Solution.ddf – increment version on Feature Folder name [vs2010: поменять имя фичи]
    5.   Feature.xml- change Title to include version number
    6. Feature.xml, change feature ID to new GUID.
    7. Workflow.xml –Change Title to include version number 
    8.  Workflow.xml-Change workflow ID to new GUID.
    9.  Workflow.xml- change CodeBesideAssembly to increment version number.
    10. Delete feature.xml, workflow.xml from Features folder, re-Deploy on DEV to write these files out again.
    11.  Run MakeCab /f Solution.ddf


    Выше описанный вариант не особо помог, и я сделал свой.
    Суть примерно такая.
    Если необходимо внести в код вф серьезные изменения, но что бы уже запущенные процы не упали, и без необходимости перенастраивать уже настроенные процессы на списках, то
    1. у сборки поднимаешь версию, например с 1.0.0.0 на 1.1.0.0
    2. В xml файле ВФ
    i. ГУИД вф (id wf) оставляешь прежним
    ii. указываешь FullAsemblyName на новую сборку
    iii. Добавляешь инфу о версии в название и дексрпишен.
    3. Deploy как новый wsp,
    i. Гуид wsp новый
    ii. Имя фичи новое, т.е. под другим именем , можно добавить к прежнему имени постфикс версии , например _1.1.0.0

    тем самым отделполоиться новая версия с новой хмл, и новые процессы будут использовать новую версию вф, а запущенные вф будут использовать старую xml со ссылкой на старую ДЛЛ.

    ОтветитьУдалить
  3. Летайте самоле... ммм... т.е. используйте SPD workflow! и будет вам щастье:)

    ОтветитьУдалить
    Ответы
    1. Согласен, тоже последнее время пользуем SDP WF. а если че надо, то пишем Custom Action :)
      Но злые языки говорят, что при больших и сложных процах SPD WF падает. Лично я не сталкивался с такими траблами, и учитывая, что у VS что у SPD под попой один и тот же движок, скорее всего при одинаковых обстоятельствах они будут вести себя одинаково :)

      Удалить
    2. Андрей, скажите а как РП созданный в дизайнере потом развертывать у заказчиков?

      Удалить
  4. На моей практике по созданию РП, пришлось изобретать XML движок процесса. В двух словах, весь процесс выглядит в виде XML, а РП к нему обращается в тот или иной момент, к примеру когда пользователь сделал Approve. В данном контексте я сделал так, что у каждого XML файла процесса есть дата с какой он будет работать. В итоге при обновлении процесса, просто выгружается модифицированный файл процесса и выставляется день с какого он будет основным.

    ОтветитьУдалить