Workflow targets что это
Как скачать и исправить ошибки Workflow.Targets
Последнее обновление: 07/04/2021 [Время на прочтение статьи: 5 мин.]
Файлы TARGETS, такие как Workflow.Targets, классифицируются как файлы Разработчик (MSBuild Target). Как файл MSBuild Target он был создан для использования в PrimoPDF 5.1.0.2 от компании Nitro.
Выпуск Workflow.Targets для Windows состоялся 11/08/2006 в Windows Vista. Самая последняя версия [версия 5.1.0.2] была представлена 07/27/2011 для PrimoPDF 5.1.0.2. Файл Workflow.Targets входит в состав Windows 10, Windows 8.1 и Windows 8.
В этой короткой статье приводятся подробные сведения о файле, шаги по устранению проблем TARGETS с Workflow.Targets и список бесплатных загрузок для каждой версии, содержащейся в нашем полном каталоге файлов.
Рекомендуемая загрузка: исправить ошибки реестра в WinThruster, связанные с Workflow.Targets и (или) PrimoPDF.
Совместимость с Windows 10, 8, 7, Vista, XP и 2000
Средняя оценка пользователей
Обзор файла
Общие сведения ✻ | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Имя файла: | Workflow.Targets | |||||||||||||||||||||||
Расширение файла: | расширение TARGETS | |||||||||||||||||||||||
Тип файла: | Разработчик | |||||||||||||||||||||||
Описание: | MSBuild Target | |||||||||||||||||||||||
Пользовательский рейтинг популярности: |
Сведения о разработчике и ПО | |
---|---|
Программа: | PrimoPDF 5.1.0.2 |
Разработчик: | Nitro |
Программное обеспечение: | PrimoPDF |
Версия ПО: | 5.1.0.2 |
Сведения о файле | |
---|---|
Размер файла (байты): | 4726 |
Дата первоначального файла: | 01/21/2008 |
Дата последнего файла: | 10/05/2019 |
Информация о файле | Описание |
---|---|
Размер файла: | 4.6 kB |
Дата и время изменения файла: | 2019:10:05 14:26:18+00:00 |
✻ Фрагменты данных файлов предоставлены участником Exiftool (Phil Harvey) и распространяются под лицензией Perl Artistic.
Что такое сообщения об ошибках Workflow.Targets?
Общие ошибки выполнения Workflow.Targets
Ошибки файла Workflow.Targets часто возникают на этапе запуска PrimoPDF, но также могут возникать во время работы программы. Эти типы ошибок TARGETS также известны как «ошибки выполнения», поскольку они возникают во время выполнения PrimoPDF. К числу наиболее распространенных ошибок выполнения Workflow.Targets относятся:
Программа: C:\Program Files (x86)\MSBuild\Microsoft\Windows Workflow Foundation\v3.0\Workflow.Targets
Среда выполнения получила запрос от этого приложения, чтобы прекратить его необычным способом.
Для получения дополнительной информации обратитесь в службу поддержки приложения.
В большинстве случаев причинами ошибок в TARGETS являются отсутствующие или поврежденные файлы. Файл Workflow.Targets может отсутствовать из-за случайного удаления, быть удаленным другой программой как общий файл (общий с PrimoPDF) или быть удаленным в результате заражения вредоносным программным обеспечением. Кроме того, повреждение файла Workflow.Targets может быть вызвано отключением питания при загрузке PrimoPDF, сбоем системы при загрузке или сохранении Workflow.Targets, наличием плохих секторов на запоминающем устройстве (обычно это основной жесткий диск) или заражением вредоносным программным обеспечением. Таким образом, крайне важно, чтобы антивирус постоянно поддерживался в актуальном состоянии и регулярно проводил сканирование системы.
Как исправить ошибки Workflow.Targets — 3-шаговое руководство (время выполнения:
Если вы столкнулись с одним из вышеуказанных сообщений об ошибке, выполните следующие действия по устранению неполадок, чтобы решить проблему Workflow.Targets. Эти шаги по устранению неполадок перечислены в рекомендуемом порядке выполнения.
Шаг 1. Восстановите компьютер до последней точки восстановления, «моментального снимка» или образа резервной копии, которые предшествуют появлению ошибки.
Чтобы начать восстановление системы (Windows XP, Vista, 7, 8 и 10):
Если на этапе 1 не удается устранить ошибку Workflow.Targets, перейдите к шагу 2 ниже.
Шаг 2. Если вы недавно установили приложение PrimoPDF (или схожее программное обеспечение), удалите его, затем попробуйте переустановить PrimoPDF.
Чтобы удалить программное обеспечение PrimoPDF, выполните следующие инструкции (Windows XP, Vista, 7, 8 и 10):
После полного удаления приложения следует перезагрузить ПК и заново установить PrimoPDF.
Если на этапе 2 также не удается устранить ошибку Workflow.Targets, перейдите к шагу 3 ниже.
Шаг 3. Выполните обновление Windows.
Когда первые два шага не устранили проблему, целесообразно запустить Центр обновления Windows. Во многих случаях возникновение сообщений об ошибках Workflow.Targets может быть вызвано устаревшей операционной системой Windows. Чтобы запустить Центр обновления Windows, выполните следующие простые шаги:
Если Центр обновления Windows не смог устранить сообщение об ошибке Workflow.Targets, перейдите к следующему шагу. Обратите внимание, что этот последний шаг рекомендуется только для продвинутых пользователей ПК.
Если эти шаги не принесут результата: скачайте и замените файл Workflow.Targets (внимание: для опытных пользователей)
Если этот последний шаг оказался безрезультативным и ошибка по-прежнему не устранена, единственно возможным вариантом остается выполнение чистой установки Windows 10.
Автоматизация глазами разработчика: Github Actions для стартапа
Основное преимущество работы в стартапе – разнообразные задачи, с которыми приходится разбираться в крайне короткие сроки за минимальный бюджет. И такие условия позволяют находить и придумывать интересные решения, которые не приняты за стандарт большими компаниями.
Сегодня поговорим о том, как можно автоматизировать обновление стенда, тестирование сборки и создание бэкапов баз данных настолько дешево, что даже бесплатно.
Логотип GitHub Actions
Однажды нам надоело сливать ветки с репозитория на виртуальную машину тестового сервера и прописывать команды создания бэкапов для всех баз данных. Также очень не хотелось из-за маленького хотфикса поднимать сервисы в Docker, поднимать сам Docker, пересобирать контейнер и запускать тесты. Мы провели исследование не только в чертогах разума, но даже на второй странице результатов поисковиков. И мы пришли к решению, которое нас более чем устроило как по цене, так и по возможностям – Github Actions.
Запуск автотестов
Приводим пример такого флоу с комментариями:
После сохранения файла в репозитории по пути RepositoryName/.github/workflows/FileName.yml мы можем перейти на вкладку «Actions» и обнаружим там наш новый флоу:
Если все было настроено верно, то при открытии pull request на master или при коммите на master (за последнее имеется отдельный котел в известном месте) Github запустит флоу, который пойдет по шагам и сначала соберет и запустит ваши контейнеры, а затем соберет и запустит проект с тестами, попутно выводя всю информацию из консоли своей виртуальной машины прямо в вашем браузере. При желании можно прикрутить бота Github, который будет сообщать о проблемах с тестами, заведет новые ишью, если тест не был пройден, а также сообщит вам в Slack/Telegram о проблемах. Все ограничено лишь фантазией и сроками. Тесты – это хорошо, но как насчет автоматизации доставки?
Автоматизация доставки
Но и тут у Github Actions есть все, что необходимо, но для полного понимания концепции стоит провести небольшой экскурс по возможностям Github:
Github Packages – используется для хранения сборок. В нашем случае мы используем его как внешний Docker registry. Подробности можно посмотреть тут: https://github.com/features/packages
Secrets – «секреты» на уровне репозитория или организации. С их помощью можно доверить Github такие ценные вещи, как логины, пароли, токены. Преимущество секретов в том, что даже в случае утраты доступа к аккаунту никто не получит доступа к секретам: Github выведет только их название, сами значения после нажатия “Save” останутся секретом для всех. Больше о секретах: https://docs.github.com/en/actions/reference/encrypted-secrets
Github Actions от сторонних разработчиков. Маркетплейс различных экшенов растет очень быстро, с каждым месяцем появляются сотни различных интеграций и возможностей для разработчиков: Jira, Azure, Telegram, Slack и так далее. На момент написания статьи в маркетплейсе было более 9000 экшенов.
Будем использовать все эти возможности, чтобы реализовать полноценный CI для обновления тестового стенда.
Подбираем подходящие экшены
Нам понадобятся экшены для логина в Github Packages, для сборки образов микросервисов, для публикации образов в Github Packages. Также нам пригодится экшен, умеющий устанавливать SSH-соединение к нашей виртуальной машине и выполнять произвольные команды.
После небольшого поиска по маркетплейсу и изучения документации был подобран следующий список экшенов:
docker/setup-qemu-action@v1 – надстройка для виртуализации
docker/setup-buildx-action@v1 – модуль Docker для сборки образов
docker/login-action@v1 – экшен для логина в Docker Registry (в нашем случае – Github Packages)
docker/build-push-action@v2 – экшен сборки и публикации образа
appleboy/ssh-action@master – экшен для инициализации подключения по SSH и выполнения скрипта
Настраиваем секреты
Один из немногих случаев, когда можно сделать скрин из приватного production-репозитория.
«Секреты» репозитория
REGISTRY_TOKER – токен для авторизации в Github Packages. Его можно получить тут: https://github.com/settings/tokens
SERVER_HOST – IP-адрес сервера в виде «192.168.100.100».
SERVER_KEY – PEM-ключ для подключения к серверу. Обычно выдается провайдером вашей виртуальной машины.
SERVER_PORT – порт сервера для SSH-соединения. По-умолчанию это 22.
SERVER_USERNAME – имя пользователя, под которым авторизовываемся на виртуальной машине.
Как было описано выше про секреты, у нас нет возможности посмотреть, чему равен тот или иной секрет: Github даже не дает нам кнопки для просмотра этих значений.
Самое время готовить стенд: напишем docker-compose и залогинимся в Github Packages. После сборки и публикации образов в Github Packages нам необходимо подключиться к удаленной машине, выгрузить и запустить новую сборку. Для этого будем использовать практически тот же docker-compose файл, что и для локальной сборки и запуска, но немного отредактируем его. Во-первых, в качестве «image» будем использовать ссылку на Github Packages, где у нас будет опубликована сборка. Во-вторых, уберем из docker-compose-файла все параметры, которые касаются именно сборки: тут они нам попросту не нужны, так как сервер отныне не отвечает за сборку.
По итогу у нас получился примерно такой файл (некоторые параметры исправлены на «template»):
Маленькое примечание: ссылка на image не должна содержать заглавных букв. Даже если имя репозитория или логин содержат заглавные буквы, в ссылке приведите их к lower-case формату. Иначе возникнут проблемы.
Опубликуем этот файл прямо в стартовом каталоге виртуальной машины, чтобы не усложнять скрипт запуска. Для примера назовем его «docker-compose.prod-ci.yml». Также, раз мы уже на машине, сразу залогинимся в Github Packages:
Важно использовать именно username, а не электронную почту. Почему-то для Github это важно и первый раз мы прогорели на этом несмотря на то, что получили сообщение об успешной авторизации. На этом работа с сервером окончена.
Пишем workflow
Просто собираем все наши знания, которые получили по ходу чтения документации соответствующих экшенов, и агрегируем их в одном файле:
На этом настройка закончена. Переходим на вкладку «Actions» и видим новый экшен «build and deploy». Триггерами этого экшена выступают два действия: публикация нового релиза и ручной запуск.
Ручной запуск экшена можно осуществить прямо со страницы экшена. Для этого нажимаем «Run workflow», выбираем ветвь, с которой будет осуществляться сборка, и запускаем.
Запуск наших экшенов
Для срабатывания триггера нового релиза зайдем в раздел «Releases» репозитория и создадим новый релиз, нажав «Draft a new release»:
Кнопка создания нового релиза
Заполним основную информацию про новый релиз:
Форма описания нового релиза
Сразу после нажатия «Publish release» сработает триггер и начнет выполнять все те шаги, которые мы описали: виртуальная машина Github’а клонирует себе репозиторий, залогинится в Github Packages, установит необходимые для Docker инструменты, соберет образы, опубликует их, затем подключится к нашей виртуальной машине и выполнит скрипт, который подключится к Github Packages, стянет последние сборки сервисов и развернет их. А за всем процессом можно зорко следить прямо в консоли запуска на Github. Разве это не прекрасно?
Бэкапы баз данных
Какие шансы, что вы не потеряете свои данные в случае, если совершаете по 2-3 обновления в неделю, многие из которых мигрируют базу?
Спойлер: шансов немного
Поэтому практически сразу встал вопрос о том, как автоматизировать создание бэкапов баз данных. Тем более, когда их несколько, а варианты с готовыми системами управления либо дорогие, либо очень дорогие. И вновь на помощь приходит Github Actions!
В прошлом примере мы рассматривали подключение к серверу и выполнение некоторых скриптов. Кажется, это нам и нужно, ведь порты к базам данных закрыты и извне подключаться к ним – идея не очень хорошая.
В каталоге db_backup создадим маленький скрипт:
Теперь переходим к репозиторию и создадим новый workflow по аналогии выше:
Итак, что мы имеем по итогу: раз в сутки (в полночь по UTC) на Github срабатывает триггер и запускает экшен, который, в свою очередь, устанавливает соединение с нашим сервером и выполняет скрипт запуска нашего бэкап-скрипта. Бэкап-скрипт пробегается по контейнерам с базами данных и создает бэкапы в соответствующих каталогах. Также у нас есть возможность создать резервные бэкапы вручную со страницы соответствующего workflow. Все, что вам останется – придумать, куда отправлять бэкапы на долгосрочное хранение.
К слову, автоматизированное создание бэкапов из 5 контейнеров занимает у нас 13-15 секунд вместе с подключением к серверу. Неплохо, не правда ли?
Заключение
Сегодня мы поговорили про варианты автоматизации, когда нужно дешево и быстро реализовать не самые сложные сценарии по запуску интеграционных тестов, обновлению стенда, созданию бэкапов. Безусловно, эти скрипты и сценарии можно и нужно улучшать, но я надеюсь, что хабровчане смогут использовать этот материал как небольшой пример, с которого можно начать автоматизацию рутины.
Начнем с истории
Наш флагманский продукт Avanpost IDM — это система управления жизненным циклом учетных записей и правами доступа работников. Управлять доступом он умеет как автоматически на основании ролевой модели, так и по заявкам. На заре становления продукта у нас была достаточно простая система самообслуживания с простым пошаговым workflow, для которого движок не требовался в принципе.
Однако, столкнувшись с крупными клиентами, мы поняли, что требуется гораздо более гибкий инструмент, поскольку их требования к процессам согласования прав доступа стремились к правилам хорошего развесистого документооборота. Проанализировав требования, мы решили разработать собственный редактор процессов в формате BPMN, подходящий под наши нужды. Про разработку редактора с использованием React.js + SVG мы расскажем чуть позже, а сегодня обсудим тему бэкенда — workflow engine или движка бизнес-процессов.
Требования
На момент начала разработки системы у нас были следующие требования к движку:
Windows Workflow Foundation (WWF)
WWF представляет собой технологию компании Microsoft для определения, выполнения и управления рабочими процессами.
Основу его логики составляет набор контейнеров для действий (активностей) и возможность из этих контейнеров строить последовательные процессы. Контейнер может быть обычным — некий шаг процесса, на котором выполняется активность. Может быть управляющим — содержащим в себе логику ветвления.
Процесс можно рисовать непосредственно в среде Visual Studio. Скомпилированная схема бизнес-процесса хранится в Хaml, что весьма удобно — формат описан, есть возможность сделать самописный дизайнер процессов. Это с одной стороны. А с другой — Xaml не самый удобный формат хранения описания — скомпилированная схема для более менее реального процесса получается огромной не в последнюю очередь из-за избыточности. Разобраться в ней очень сложно, а разбираться придется.
Но если со схемами рано или поздно можно постичь дзен и научится читать их, то вот отсутствие прозрачности работы самого движка добавляет хлопот уже во время эксплуатации системы пользователями. Когда ошибка исходит и недр Wf, узнать на 100%, в чем именно была причина сбоя, удается не всегда. Закрытость исходников и относительная монструозность делу не помогает. Часто фиксить баги приходилось по симптомам.
Справедливости ради тут стоит уточнить, что проблемы, описанные выше, по большей части преследовали нас из-за сильной кастомизации поверх Wf. Кто-нибудь из читателей точно скажет, что мы сами создали себе кучу проблем, а потом героически их решали. Нужно было делать самописный движок с самого начала. В целом, они будут правы.
Workflow Core
Workflow Core — это свободно распространяемый движок бизнес-процессов. Он разрабатывается под лицензией MIT, т.е его можно спокойно использовать в коммерческой разработке.
Активно делает его один человек, еще несколько периодически делают pull request. Есть порты на другие языки (Java, Python и еще несколько).
Движок позиционируется как легковесный. По сути это просто некий хост для последовательного выполнения сгруппированных по каким-либо бизнес-правилам действий.
У проекта есть документация в виде wiki. К сожалению, она описывает далеко не все возможности движка. Однако требовать полноценную документацию будет нагло — проект opensource, поддерживается одним энтузиастом. Поэтому Wiki вполне будет вполне достаточно для начала работы.
«Из коробки» есть поддержка хранения состояния процессов во внешних хранилищах (persistence storage). Стандартно идут провайдеры для:
Написать свой провайдер не составляет проблем. Берем исходники любого стандартного и делаем по примеру.
Поддерживается горизонтальное масштабирование, т.е можно запускать движок сразу на нескольких нодах, имея при этом одну точку хранения состояний процессов (один persistence storage). При этом размещение внутренней очереди задач движка должно быть в общем хранилище (rabbitMQ, как вариант). Для исключения выполнения одной задачи несколькими нодами одновременно предусмотрен диспетчер блокировок. По аналогии с провайдерами внешнего хранилища, есть стандартные реализации:
Знакомство с чем-то новым проще всего начать с примера. Так и поступим. Я опишу с самого начала построение простого процесса, попутно давая свои пояснения. Пример может показаться до невозможности простым. Соглашусь — он простой. Самое то для начала.
Step (Шаг)
Шаг — это этап процесса, на котором выполняются какие либо действия. Весь процесс строится из последовательности шагов. Один шаг может выполнять много действий, может выполняется повторно, например, по некоторому событию извне. Есть набор шагов, которые наделены логикой «из коробки»:
Само собой, на одних встроенных примитивах процесс не постоишь. Нужны шаги, которые выполняют бизнес-задачи. Поэтому пока отложим их в сторону и сделаем шаги со своей логикой. Для этого нужно наследоваться от абстракции StepBody.
Метод Run выполняется, когда процесс заходит в шаг. В него и нужно разместить необходимую логику.
Шаги поддерживают внедрение зависимостей. Для этого достаточно зарегистрировать их в том же контейнере, что и необходимые зависимости.
Очевидно, что процессу нужен свой контекст — место, куда можно складывать промежуточные результаты выполнения. В wf core есть свой контекст выполнения процесса, который хранит информацию о его текущем состоянии. Получить доступ к нему можно, используя переменную context из метода Run(). В дополнение ко встроенному мы можем использовать свой контекст.
Подробнее способы описания и регистрации процесса разберем чуть ниже, пока просто определим свой некий класс — контекст.
В переменные Number запишем числа; в переменную StepResult — результат выполнения шага.
С контекстом определились. Можно писать свой шаг:
Логика крайне простая: на вход приходят два числа и название операции. Результат операции записывается в выходную переменную Result. Если операция не определена, то результат будет none.
С контекстом мы определились, шаг с нужней нам логикой тоже есть. Теперь нужно зарегистрировать наш процесс в движке.
Описание процесса. Регистрация в движке.
Описать процесс можно двумя способами. Первый — это описание в коде — хардкод.
Непосредственно описание будет внутри метода Build. Поля Id и Version также необходимо заполнить. Wf core поддерживает версионность процессов — можно зарегистрировать n версий процесса с одинаковым идентификатором. Это удобно, когда требуется обновить существующий процесс и при этом дать «дожить» уже существующим задачам.
Опишем простой процесс:
Если перевести на «человеческий» язык, получится примерно так: процесс начинается с шага CustomStep. Значение поля шага Input1 берется из поля контекста Number1, Значение поля шага Input2 берется из поля контекста Number2, полю Action жестко указано значение «sum». Выходные данные из поля Result записывается в поле контекста StepResult. Завершить процесс.
Согласитесь, код получился весьма читаемый, вполне можно разобраться, даже не имея особых познаний в C#.
Добавим к нашему процессу еще один шаг, который будет выводить в лог результат выполнения предыдущего шага:
Теперь после шага с операцией сложения следует шаг вывода результата в лог. На вход мы передаем переменную Result и контекста, в которую на прошлом шаге записали результат выполнения. Возьму на себя смелость утверждать, что подобное описание через код (хардкод) в реальных системах будет малополезным. Разве что для каких-то служебных процессов. Куда более интересно иметь возможность хранить схему отдельно. Как минимум, нам не придется пересобирать проект каждый раз, когда нужно что-то поменять в процессе или добавить новый. Эту возможность wf core предоставляет посредством хранения схемы json. Продолжим расширять наш пример.
Json описание процесса
Далее я не буду приводить описание через код. Это не особо интересно, и только раздует статью.
Wf core поддерживает описание схемы в json. На мой взгляд, json более нагляден чем xaml (хорошая тема для холивара в комментариях 🙂 ). Структура файла довольно простая:
В поле DataType указывается полное имя класса контекста и имя сборки, в которой он описан. В Steps хранится коллекция всех шагов процесса. Заполним элемент Steps:
Давайте разберем подробнее структуру описание шага через json.
Поля Id и NextStepId хранят идентификатор данного шага и указатель, какой шаг может быть следующим. При этом порядок следования элементов коллекции неважен.
StepType аналогичен полю DataType, содержит полное имя класса шага (тип, который наследуется от StepBody и реализует логику шага) и название сборки. Дальше интереснее — объекты Inputs и Outputs. Они задаются в виде маппинга.
В случае Inputs имя элемента json — это имя поля класса нашего шага; значение элемента — имя поля в классе — контексте процесса.
Для Outputs наоборот, имя элемента json — это имя поля в классе — контексте процесса; значение элемента — имя поля класса нашего шага.
Разнообразим схему стандартными примитивами. Добавим условный шаг If и обработку внешнего события.
Примитив If. Тут начинаются сложности. Если вы привыкли к bpmn и рисуете процессы в этой нотации, то вас ждет легкая подстава. По документации шаг описывается следующим образом:
Нет ощущения, что что-то тут не так? У меня есть. На вход шага задается Condition — выражение. Дальше задаем список шагов внутри массива Do (действия). Так, а где ветка False? Почему нет массива Do для False? На самом деле есть. Подразумевается, что ветка False — это просто проход дальше по процессу, т.е по указателю в NextStepId. Первое время я постоянно путался из-за этого. Окей, тут разобрались. Хотя нет. Если действия по процессу в случае True нужно класть внутрь Do, это же какой «красивый» json тогда будет. А если там этих If вложенных с десяток? Все уедет вбок. А еще говорят, что схему на xaml трудно читать. Есть небольшой хак. Просто взять монитор пошире. Немного выше упоминалось, что порядок шагов в коллекции значение не имеет, переход идет по указателям. Это можно использовать. Добавим еще один шаг:
Догадываетесь, к чему я веду? Верно, мы вводим служебный шаг, который транзитом переводит процесс на шаг в NextStepId.
Обновим нашу схему:
В шаге If проверяется, пустой ли результат выполнения шага Eval. Если не пустой, то выводим результат, если пустой — то сообщение «Empty result». Шаг Jump переводит процесс в шаг Output, который находится вне коллекции Do. Таким образом, мы сохранили «вертикальность» схемы. Также таким способом можно переходить по условию на n шагов назад, т.е. организовывать цикл. В wf core есть встроенные примитивы для циклов, но они не всегда удобны. В bpmn, например, циклы организуются через If.
Использовать этот подход или стандартный, решать уже вам. Для нас такая организация оказалась шагов удобнее.
WaitFor
Примитив WaitFor дает возможность внешнему миру влиять на ход процесса, когда он уже запущен. Например, если на этапе процесса требуется одобрение дальнейшего хода каким-либо пользователем. Процесс будет стоять на шаге WaitFor, пока в него не придет событие, на которое он подписан.
Немного поясню параметры.
CancelCondition — условие прерывания ожидания. Предоставляет возможность прервать ожидание события и пойти дальше по процессу. Например, если процесс одновременно ждет n разных событий (wf core поддерживает параллельное выполнение шагов), ждать прихода всех не требуется, в этом случае нам поможет CancelCondition. Добавляем в переменные контекста логический флаг и при получении события выставляем флаг в значение true — все шаги WaitFor завершатся.
EventName и EventKey — имя и ключ события. Поля нужны, чтобы в реальной системе с большим количеством одновременно работающих процессов, различать события, т.е. чтобы движок понимал, какое событие для какого процесса и какого шага предназначено.
EffectiveDate — опциональное поле, добавляет событию метку времени. Может пригодится в случае, если нужно опубликовать событие «в будущее». Чтобы оно опубликовалось сразу параметр можно оставить пустым или задать текущее время.
Далеко не во всех случаях удобно делать отдельный шаг для обработки реакций извне, скорее даже обычно он будет избыточен. Лишнего шага можно избежать, добавив в обычный шаг ожидание внешнего события и логику его обработки. Дополним шаг CustomStep подпиской на внешнее событие:
Мы воспользовались стандартным методом расширения WaitForEvent(). Он принимает на вход уже упомянутые ранее параметры EventName, EventKey и EffectiveDate. После выполнения логики такого шага процесс встанет в ожидание описанного события и снова вызовет метод Run() в момент публикации события в шине движка. Однако в текущем виде мы не можем различить моменты первичного входа в шаг и вход после события. А хотелось бы как-то разделить логику до-после на уровне шага. И в этом нам поможет флаг EventPublished. Он находится внутри общего контекста процесса, получить его можно так:
Опираясь на этот флаг можно спокойно разделить логику на до и после внешнего события.
Важное уточнение — по задумке создателя движка один шаг может быть подписать только на один эвент и среагировать на него один раз. Для некоторых задач это весьма неприятное ограничение. Нам даже пришлось «допиливать» движок, чтобы от этого нюанса уйти. Сейчас в этой статье их описание пропустим, иначе статья никогда не закончится :). Более сложные практики использования и примеры доработок будут освещаться в последующих статьях.
Регистрация процесса в движке. Публикация события в шину.
Итак, с реализацией логики шагов и описания процесса разобрались. Осталось самое главное, без чего процесс не будет работать — описание нужно зарегистрировать.
Воспользуемся стандартным методом расширения AddWorkflow(), который разместит в нашем IoC контейнере свои зависимости.
IServiceCollection — интерфейс — контракт коллекции описаний сервисов. Он живет внутри DI от Microsoft (подробнее про него можно почитать тут)
WorkflowOptions — базовые настройки движка. Самому их задавать не обязательно, стандартные значение вполне приемлемы для первого знакомства. Едем дальше.
Если процесс описывался в коде, то регистрация происходит так:
Если процесс описан через json, то его нужно регистрировать так (само собой, json описание нужно предварительно загрузить из места хранения):
Далее для обоих вариантов код будет одинаков:
Параметр definitionId — идентификатор процесса. То, что записано в поле Id процесса. В данном случае идентификатор = SomeWorkflow.
Параметр version указывает, какую версию процесса запустить. Движок предоставляет возможность регистрировать сразу n версий процесса с одним идентификатором. Это удобно, когда требуется внести изменения в описание процесса, не ломая уже запущенные задачи — новые будут создаваться по новой версии, старые спокойно доживут на старой.
Параметр context — экземпляр контекста процесса.
Методы host.Start() и host.Stop() запускают и останавливают хостинг процессов. Если в приложении запуск процессов — прикладная задача и выполняется периодически, то следует останавливать хостинг. Если приложение имеет основным направлением выполнение различных процессов, то хостинг можно не останавливать.
Для передачи сообщений из внешнего мира в шину движка, которая потом распределит их по подписчикам есть метод:
Описание его параметров было выше в статье (см. часть про WaitFor примитив).
Заключение
Мы определенно рисковали, когда приняли решение в пользу Workflow Core — opensource проекта, который активно разрабатывает один человек, да еще и с весьма бедной документацией. И реальных практик использования wf core в рабочих системах (кроме нашей) вы, скорее всего, не найдете. Конечно, выделив отдельный слой абстракций, мы подстраховались на случай неуспеха и необходимости быстро вернутся к WWF, например, или самописному решению, но все пошло вполне неплохо и неуспех не настал.
Следом идет открытость исходников. Работая с WWF и получая разнообразные ошибки из его недр, возможность хотя бы почитать исходники была бы очень кстати. Не говоря уже о том, чтобы что-то в них поменять. Тут с Workflow Core полная свобода (в том числе по лицензированию — MIT). Если вдруг появляется ошибка из недр движка, просто качаем исходники из github и спокойно ищем причину ее возникновения. Да просто возможность запустить движок в режиме отладки с точками останова уже сильно облегчает процесс.
Само собой, решив одни проблемы, Workflow Core принес уже свои, новые. Нам пришлось внести ощутимое количество изменений в ядро движка. Но. Работы по «допиливанию» под себя обошлись дешевле по времени, чем разработка собственного движка с нуля. Итоговое решение получилось вполне приемлемо по скорости и стабильности работы, позволило нам на текущий момент забыть про проблемы с движком и сфокусироваться на развитии бизнес-ценности продукта.
- Trojan multi locked folder что это
- Raiffeisen life ppi max что это как отключить