Как создать приложение Optimizely Connect Platform (OCP)

Как создать приложение Optimizely Connect Platform (OCP)

Платформа Optimizely Connect (OCP): объединение систем в экосистеме Optimizely One и изучили, как это позволяет системам Optimizely One обмениваться данными чисто и последовательно. Этот пост основан на этом фундаменте и представляет собой более практичный и ориентированный на разработчиков взгляд на платформу.

В этой статье мы рассмотрим процесс создания приложения OCP, которое подключается к Cloudinary, — от создания проекта и определения схемы данных до реализации заданий, проверки приложения и публикации интеграции.

Начиная

Прежде чем мы начнем создавать коннектор Cloudinary, необходимо выполнить несколько предварительных условий.

1. Получите учетную запись разработчика OCP.

Запросите доступ у Optimizely, чтобы получить инструменты и разрешения. См. Оптимизация документации для более подробной информации.

2. Настройте среду разработки

Требования:

Проверьте вашу настройку:

1ocp --version

3. Создайте новое приложение

1ocp app init

Это создает:

  • Определение приложения

  • Схема YAML

  • Папка с вакансиями

  • Папка функций

  • Форма настроек

Шаблонное приложение является отличной отправной точкой и обеспечивает основу для соединителя Cloudinary, используемого в этом примере.

Создание приложения

Теперь, когда приложение создано, мы можем перейти к созданию коннектора Cloudinary.

1. Настройки приложения

Нам необходимо получить учетные данные и конечную точку интеграции, чтобы приложение могло аутентифицироваться и взаимодействовать с Cloudinary. Можно расширить интерфейс OCP, чтобы захватывать их и безопасно сохранять для использования в приложении.

settings.yml

'settings.yml' файл используется для определения формы. В этой форме сохраняются все настройки, необходимые вашему приложению. Форма может содержать разделы, позволяющие логически группировать настройки.

1sections:
2  - key: authorisation
3    label: Authorisation
4    elements:
5    - type: text
6      key: url
7      label: Integration URL
8      help: The URL of the Cloudinary account to integrate with. This is typically in the format `https://api.cloudinary.com/v1_1/>`.
9      hint: https://api.cloudinary.com/v1_1/>
10      required: true
11    - type: text
12      key: username
13      label: Username
14      help: The username for the Cloudinary account.
15      required: true
16    - type: secret
17      key: password
18      label: Passwword
19      help: The password for the Cloudinary account.
20      required: true
21    - type: button
22      label: Save
23      action: save
24      style: primary
25    - type: button
26      label: Start Sync
27      action: sync
28

Форма может содержать поля разных типов. Поля могут включать проверку, а также ссылаться на внешние источники данных. Более подробную информацию можно найти в документации Optimizely: Дальнейшее чтение.

Жизненный цикл формы

Как описано выше, 'settings.yml' file используется для определения формы, но нам также нужен механизм взаимодействия со значениями, когда пользователь их вводит.

'Lifecycle.ts' Файл содержит функцию onSettingsForm, которая точно выполняет эту задачу.

1  public async onSettingsForm(
2    section: string,
3    _action: string,
4    formData: SubmittedFormData
5  ): Promise<LifecycleSettingsResult> {
6    const result = new LifecycleSettingsResult();
7    try {
8
9      if (section === 'authorisation') {
10
11        switch (_action) {
12        case 'save':
13          await storage.settings.put(section, formData);
14          await registerWebhooks(formData.url as string,
15                                 formData.username as string,
16                                 formData.password as string);
17
18          break;
19        }
20      }
21
22      return result;
23
24    } catch {
25      return result.addToast(
26        'danger',
27        'Sorry, an unexpected error occurred. Please try again in a moment.'
28      );
29    }
30  }

Приведенный выше код срабатывает, когда ‘Сохранять‘ нажата кнопка формы. В фрагменте кода

  1. Значения формы сохраняются в хранилище OCP.

  2. Пользовательская функция ‘зарегистрироватьсяВебхукиназывается. При этом вебхук OCP регистрируется в Cloudinary (подробнее об этом позже).

Read more:  БЕЛЫЙ ДОМА ОБморОК | Руководитель компании Оземпича потерял сознание в Овальном кабинете в присутствии Трампа

2. Схема данных

Поскольку это ‘Приложение синхронизации данных‘, нам нужно определить объекты данных, в которых будут храниться данные изображения, которые мы синхронизируем с Cloudinary.

Схемы объектов данных определяются как YML и должны быть расположены в папке 'schema' папка.

1name: cloudinary_image
2display_name: Cloudinary Image
3fields:
4  - name: asset_id
5    type: string
6    display_name: Asset ID
7    description: Unique identifier for the asset in Cloudinary.
8    primary: true
9
10  - name: public_id
11    type: string
12    display_name: Public ID
13    description: Public identifier for the asset, used in URLs and API calls.
14
15  - name: format
16    type: string
17    display_name: Format
18    description: Document format, e.g. jpg, png, etc.
19
20  - name: version
21    type: number
22    display_name: Version
23    description: Document version
24
25  - name: resource_type
26    type: string
27    display_name: Resource Type
28    description: Type of resource, e.g. image, video, etc.
29
30  - name: type
31    type: string
32    display_name: Type
33    description: Type of upload, e.g. upload, private, authenticated, etc.
34

3. Вакансии

В Optimizely есть концепцияРабота‘. Они предназначены для поддержки длительных процессов, например обработки начальной загрузки данных. Задания можно планировать (через cron) или запускать по требованию.

Основные понятия

Хотя задание поддерживает длительные процессы, оно должно быть написано так, чтобы обработка выполнялась пакетно, причем каждый пакет обрабатывает подмножество общих данных. В примере Cloudinary мы не будем загружать все изображения одновременно; мы будем загружать их меньшими частями.

Подготовить

Этот метод вызывается для настройки пакета для обработки задания. Здесь определяется состояние начальной загрузки или состояние предыдущего запуска передается следующему пакетному процессу.

Выполнять

Здесь осуществляется фактическая обработка. Он получает состояние, которое используется для определения следующего набора изображений для загрузки.

Время, необходимое для выполнения процесса, должно быть в пределах 60 секунд. Родительский процесс OCP может завершить что-либо более длительное.

1  public async perform(
2    status: HistoricalImportJobStatus
3  ): Promise<HistoricalImportJobStatus> {
4    const state = status.state;
5    let encounteredError = false;
6    try {
7      // fetch some assets from our API
8      const response = await this.fetch(state.cursor, 500);
9
10      logger.info(`response ${response.status}, ${response.statusText} `);
11
12      if (response.ok) {
13
14        const result = (await response.json()) as HistoricalImportResult;
15        const cursor = result.next_cursor ?? '';
16
17        // Update our state so the next iteration can continue where we left off
18        state.cursor = cursor;
19        state.count += result.resources.length;
20
21        // Transform our assets and send a batch to Optimizely Hub
22        if (result.resources.length > 0) {
23          await odp.object('cloudinary_image', result.resources.map(transformAssetToPayload));
24        }
25
26        // In this example, 0 assets means we have imported all the data
27        if (result.resources.length === 0 || cursor.length === 0) {
28          // Notify the customer we completed the import and provide some information to show it was successful
29          await notifications.success(
30            'Historical Import',
31            'Completed Historical Import',
32            `Imported ${state.count} assets.`
33          );
34          status.complete = true;
35          return status;
36        }
37
38      } else {
39        logger.error(
40          'Historical import error:',
41          response.status,
42          response.body.read().toString()
43        );
44        encounteredError = true;
45      }
46    } catch (e) {
47      // Log all handled errors for future investigation. Customers will not see these logs.
48      logger.error(e);
49      encounteredError = true;
50    }
51
52    // If we encountered an error, backoff and retry up to 5 times
53    if (encounteredError) {
54      if (state.retries >= 5) {
55        // Notify the customer there was a problem with the import
56        await notifications.error(
57          'Historical Import',
58          'Failed to complete historical import',
59          'Maximum retries exceeded'
60        );
61        status.complete = true;
62      } else {
63        state.retries++;
64        await this.sleep(state.retries * 5000);
65      }
66    }
67
68    // Our state has been updated inside status so we know where to resume
69    return status;
70  }

В приведенном выше коде я получаю следующие 500 изображений из Cloudinary. Если есть изображения, я сохраню их в базе данных OCP; в противном случае я предполагаю, что все изображения загружены, и обработка прекращается.

Read more:  Израильский огонь снова убивает, как ищущие оказания помощи в Газе, когда посланник США встречается с семьями заложников

Полный код задания см. в моем репозитории на GitHub: Историческийимпорт.js

4. Вебхуки

Вебхуки позволяют обновлять данные по требованию, а не по расписанию. Это означает, что как только в Cloudinary будет добавлено новое изображение, база данных OCP также будет обновлена.

У OCP есть ‘Функция‘, что позволяет нам создать вебхук

Определить функции

Вам необходимо зарегистрировать свою функцию в 'app.yml' файл.

1
2functions:
3  handle_new_asset:
4    entry_point: HandleNewAsset
5    description: Webhook that handles new assets uploaded to Cloudinary
Реализация функции
1import { logger, Function, Response } from '@zaiusinc/app-sdk';
2import { odp } from '@zaiusinc/node-sdk';
3import { transformNotificationToPayload } from '../lib/transformAssetToPayload';
4import { CloudinatyImageUploadNotification } from '../data/CloudinatyImageUploadNotification';
5
6export class HandleNewAsset extends Function {
7  1011
12  public async perform(): Promise<Response> {
13
14    const notifcation = this.request.bodyJSON as CloudinatyImageUploadNotification;
15
16    if (!notifcation?.asset_id) {
17      return new Response(400, 'Unable to process request, invalid notification');
18    } else {
19      try {
20
21        const payload = transformNotificationToPayload(notifcation);
22        await odp.object('cloudinary_image', payload);
23
24        // return the appropriate status/response
25        return new Response(200);
26      } catch (e: any) {
27        logger.error(e);
28        return new Response(500, `An unexpected error occurred: ${e}`);
29      }
30    }
31  }
32}

Когда в Cloudinary добавляется новое изображение, оно вызывает зарегистрированный вебхук (см. 'Lifecyce.ts'). Затем вызывается функция, показанная выше, которая считывает полезную нагрузку Cloudinary и обновляет базу данных OCP.

Развертывание приложения

Приложение невозможно запустить локально; его можно запустить только на платформе OCP. Это означает, что крайне важно писать комплексные модульные тесты для проверки функциональности приложения. Интерфейс командной строки OCP ожидает этого и выполнит все тесты, обнаруженные в проекте. Платформа тестирования Jest устанавливается при создании шаблона приложения.

Read more:  «Активный стрелок» или жертва агента ICE? Двойные иски после убийства в Лос-Анджелесе

Хотя поначалу это может показаться ограничительным, сочетание модульных тестов и проверки CLI делает развертывание предсказуемым и повторяемым.

Чтобы протестировать и развернуть приложение, вам необходимо выполнить следующие шаги:

  1. ocp app validate – Конфигурация проверена и выполнены все модульные тесты.

  2. ocp app prepare – Приложение подготовлено к публикации.

  3. ocp directory publish [email protected] – Опубликуйте приложение в OCP.

  4. ocp directory install [email protected] TRACKER_ID – Установите приложение в свой экземпляр.

Доступ к журналам

На вкладке «Устранение неполадок» вашего приложения будут отображаться все сообщения, записанные вами в журналы.

Устранение неполадок OCP

Заключительные мысли

Платформа Optimizely Connect предоставляет надежную и простую основу для интеграции внешних систем в экосистему Optimizely One. Для команд, уже работающих с Optimizely One, OCP устраняет большую часть операционных накладных расходов, традиционно связанных с разработкой интеграции.

Я обнаружил, что разработка соединителя Cloudinary на основе шаблонного приложения очень быстрая и простая.

Исходный код приложения доступен в моем репозитории GitHub: https://github.com/andrewmarkham/Cloudinary/

По теме

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.