Найти в Дзене
IT4BIM

Оркестрация Revit на сервере: как параллельно выполнять типовые задачи в контексте Revit.

Введение

В крупных BIM-проектах часто возникает необходимость выполнять одни и те же операции для множества моделей. Это может быть экспорт в различные форматы (NWC, IFC), извлечение данных для последующего анализа или даже более сложные задачи, связанные с автоматизированной обработкой моделей.

Когда моделей становится слишком много, выполнение этих операций вручную становится неэффективным, а в случае работы с Revit и Navisworks — еще и ресурсоемким. Оптимальное решение — организовать серверную оркестрацию этих процессов, где задания выполняются автоматически по заданному сценарию.

В этой статье мы рассмотрим, как можно настроить управление процессами Revit на сервере, чтобы выполнять BIM-задачи в пакетном режиме. Такой подход позволяет:

  • Автоматизировать экспорт моделей в форматы NWC и IFC.
  • Выгружать данные из моделей в базу данных.
  • Выполнять любые другие задачи, которые необходимо повторять для каждой модели компании.

Оркестрация этих процессов на сервере значительно сокращает время обработки, устраняет человеческий фактор и делает работу с моделями более предсказуемой и управляемой.

Контроллер для работы с очередью задач Серверная часть API уровень

Этот контроллер представляет собой упрощенный пример API, который управляет очередью задач в памяти сервера. Основная цель — показать, как можно добавлять и извлекать задачи с помощью ConcurrentQueue.

-2

Как работает этот контроллер

  • Метод Get() – Возвращает элемент из очереди и удаляет его, чтобы задачу дважды в работу не попала
  • Метод Post(string value) – добавляет новую задачу в очередь. В реальном сценарии это может быть путь к файлу или информация о задаче.

Ограничения этого решения

  • Очередь хранится в памяти (ConcurrentQueue<string>), что означает, что задачи теряются при перезапуске сервера.
  • Такой подход не подходит для многосерверной среды (при горизонтальном масштабировании).
  • Нет механизма повторного выполнения задач или отслеживания их состояния.

Что использовать в реальном проекте?

Для надежной обработки задач лучше использовать брокеры сообщений:

  1. RabbitMQ – популярный брокер сообщений, хорошо подходит для распределенной обработки задач.
  2. Kafka – если требуется высокая пропускная способность и обработка событий в реальном времени.
  3. Azure Queue Storage или AWS SQS – если приложение развернуто в облаке.
  4. Redis (List) – можно использовать как простую распределенную очередь с возможностью сохранения данных.

Если тебе нужно внедрить RabbitMQ или другой брокер в этот проект, могу помочь с этим, пиши в тг.

Описание класса RevitRunner, используется на серверной части, вынесен в библиотеку

Класс RevitRunner предназначен для запуска Revit с использованием журнала (journal file). Этот журнал может содержать команды, например, для автоматической выгрузки NWC или выполнения других задач.

🔹 Как это работает?

  1. Создаем объект RevitRunner, указывая путь к файлу журнала (.txt) и версию Revit, который нужно запустить.
  2. Вызываем метод Run(), чтобы запустить процесс Revit с переданными аргументами.
  3. Если нужно принудительно закрыть Revit, вызываем метод Kill().
  4. При уничтожении объекта RevitRunner (деструктор ~RevitRunner()), Revit автоматически завершается. Но рекомендуется самостоятельно вызывать метод Kill
-3

После того как написали обертку для запуска процесса Revit нам нужно временно перейти к настройке и написанию плагина под Revit

Шаг 1: Создание файла манифеста

Первым делом необходимо написать файл манифеста для нашей команды. Этот файл определит параметры и настройки для плагина.

-4

Шаг 2: Обновление файла журнала

Затем нужно вызвать нашу команду в файле журнала (Runner.txt). Важно, чтобы ID команды в файле манифеста и в журнале были одинаковыми. Эта согласованность критически важна для правильного выполнения и отладки.

-5

Обратите внимание чтобы id команды в файле манифеста и журнале были одинаковы

Шаг 3: Реализация команды

После настройки манифеста и журнала переходим к третьему шагу — написанию команды, которая будет выполнять задачи внутри Revit.

-6

Данный класс RevitCommand реализует интерфейс IExternalCommand, что позволяет вызывать его из Revit. Он работает в бесконечном цикле, запрашивая сервер на наличие новых задач. Если задача найдена, она передается в обработку.

Метод Execute — это точка входа команды в Revit. Он просто запускает ProcessQueue(), который работает в вечном цикле.

Метод ProcessQueue:

  1. Отправляет GET-запрос к http://localhost:5140/RevitTask, чтобы забрать новую задачу из очереди.
  2. Если задача найдена (response.IsSuccessStatusCode), она разбирается в JObject, и достается task.
  3. Если задача не пуста, передает её в ExecuteTask().
  4. Если задач нет, ждет 10 секунд (Thread.Sleep(10000)) перед следующим запросом.
  5. В случае ошибки исключение обрабатывается, и поток снова уходит в ожидание.

Метод ExecuteTask отвечает за выполнение задачи. Здесь можно реализовать экспорт в IFC/NWC, валидацию данных, выгрузку в базу и другие процессы.

Итог

Этот код обеспечивает автоматическое выполнение задач внутри Revit. Команда постоянно мониторит сервер и берет задачи в работу без необходимости ручного вмешательства. Такой подход отлично подходит для автоматизированного экспорта моделей, валидации данных или других процессов, требующих запуска в среде Revit.

Шаг 4: Настройка среды разработки

Для вашего удобства был создан профиль, который позволяет запускать сервер и клиент одновременно. Это даст возможность отлаживать приложение Revit и сервер одновременно.

-7

Удобный доступ до API реализован с помощью Scalar. И с его помощью в данном тестовом проекте появляется возможность добавить задачу в очередь

-8

Шаг 5: Параллельное выполнение на нескольких экземплярах Revit

Теперь давайте перейдем к самой интересной части — выполнению нашей задачи параллельно в нескольких экземплярах Revit. Для этого предварительно в файле appsettings.json необходимо добавить поля, чтобы упростить настройку сервера.

-9

И после создать класс, с помощью которого на серверной стороне мы сможем запускать экземпляры Revit. Данный код позволяет автоматизировано запустить Revit-ы на выполнение нашей задачи в бесконечном цикле. И теперь через API мы можем добавлять сколько угодно задач и они будут параллельно выполняться 3 Revit-ами.

-10

Так же не забываем зарегистрировать наш сервис builder.Services.AddHostedService<RevitBackgroundService>();

Вывод

Теперь у нас появилась возможность пакетно запускать задачи, выполнение которых возможно только в контексте Revit. Это значительно может значительно увеличить производительность труда BIM отдела, ведь появляется возможность подключить уже существующий плагин в эту логику и пакетно обрабатывать большой объем моделей на серверной машине или даже на нескольких машинах одновременно.