Масштабирование вычислительных ресурсов в Salesforce
6 декабря 2022 г.Платформа разработки Salesforce предлагает множество мощных функций, позволяющих предоставить вашей команде приложения, открывающие новые рабочие процессы. В течение многих лет платформа работала на трех технологиях: Visualforce< /a> (для просмотра данных), Apex ( для обработки данных) и Salesforce (для хранения данных).
Apex похож на многие другие объектно-ориентированные языки и имеет синтаксис, подобный Java. Однако Apex работает непосредственно на серверах Salesforce, что позволяет разработчикам создавать и развертывать приложения, не беспокоясь о том, где их разместить или как защитить свои данные.
Проблемы Apex и долго выполняемых команд
Приложения, созданные на платформе Salesforce, работают на ее многопользовательской архитектуре, поэтому ресурсы сервера, такие как ЦП и память распределяется между различными организациями. Однако с общими ресурсами не сможет ли код приложения одной организации потреблять столько процессорного времени и памяти, что это повлияет на других пользователей в той же организации? Примером этого может быть команда, выполнение которой занимает несколько минут.
Salesforce предотвращает подобные ситуации, ограничивая запуск приложений на своей платформе. Если какое-либо приложение может мешать работе других пользователей, оно не может завершить выполнение своей команды. Длительно работающие программы потенциально могут прерывать другую работу, потребляя ограниченные доступные ресурсы.
Если да, то как разработчики Salesforce могут создавать приложения, выполняющие длительные команды, которые могут масштабироваться по мере роста числа пользователей, не влияя на производительность?
Функции Salesforce приходят на помощь
Введите функции Salesforce, представляющие собой небольшие программы, написанные на JavaScript, TypeScript или Java. и развернуты на серверах Salesforce. Функции могут выполнять ресурсоемкую работу и вызываться непосредственно из Apex. Когда функция Salesforce завершает запрос, она может отправить свои результаты обратно в исходное приложение Apex, которое затем выполняет любые дополнительные задачи с этими результатами.
Функции Salesforce запускаются в собственном контейнере и не влияют на других арендаторов на платформе Salesforce. Ограничения памяти и ЦП намного выше, что позволяет выполнять более длительные и сложные задачи. Поскольку функции Salesforce работают на платформе Salesforce, безопасность встроена; нет риска потери конфиденциальности, так как все работает в пределах одной границы доверия.
В этой статье мы подробно рассмотрим, как перенести длительную операцию Apex в функцию Salesforce, а также дадим несколько общих советов по пакету Salesforce DX.
Предпосылки
Эта статья потребует от вас некоторого понимания Apex и TypeScript, но не беспокойтесь, если вы не являетесь экспертом. Мы рассмотрим каждый фрагмент кода, чтобы объяснить, что происходит.
Несмотря на то, что завершенная версия нашего кода доступна в виде репозитория GitHub, вы также можете загрузить некоторые инструменты CLI. который Salesforce предоставляет для продолжения (или для ваших собственных будущих проектов).
- Сначала установите интерфейс командной строки sfdx, который помогает упростить стандартные операции для разработчиков Salesforce при создании приложений.
- Важно, чтобы все, что вы создаете и развертываете, не влияло на вашу «настоящую» производственную организацию Salesforce. Итак, создайте отдельную рабочую организацию, с которой может взаимодействовать это приложение. с. Чтобы создать собственную временную организацию, создайте бесплатную учетную запись Developer Edition.
- Чтобы использовать функции Salesforce, вам необходимо зарегистрироваться для пробной версии функций Salesforce связавшись с менеджером по работе с клиентами Salesforce.
- Наконец, вы также можете установить расширение Salesforce VS Code, чтобы немного упростить развертывание своего кода. Этот шаг не является обязательным.
Обзор существующего кода
Откройте файл по адресу force-app/main/default/classes/Dogshow.cls
и просмотрите его содержимое:
public class Dogshow {
public static void updateAccounts() {
// Get the 5 oldest accounts
Account[] accounts = [SELECT Id, Description FROM Account ORDER BY CreatedDate ASC LIMIT 5];
// Set HTTP request
HttpRequest req = new HttpRequest();
req.setEndpoint('https://dog.ceo/api/breeds/image/random');
req.setMethod('GET');
// Create a new HTTP object to send the request object
Http http = new Http();
HTTPResponse res = http.send(req);
String body = res.getBody();
Map<String, String> m = (Map<String, String>) JSON.deserialize(jsonStr, Map<String, String>.class);
String dogUrl = m.get('message');
// loop through accounts and update the Description field
for (Account acct : oldAccounts) {
acct.Description += ' And their favorite dog can be found at ' + dogUrl;
}
// save the change you made
update accounts;
}
}
Эти 30 строк выполняют довольно простую функцию:
- Он захватывает пять самых старых учетных записей Salesforce, используя SOQL.
- Он отправляет HTTP-запрос к сайту https://dog.ceo/dog-api/, возвращает объект JSON со случайным URL-ссылкой на очень милую собачку.
- Затем код Apex обновляет описание этих пяти учетных записей, чтобы указать, что эта собака является их любимой.
Этот код довольно безобиден, но он вводит две ситуации, представляющие некоторые реальные проблемы:
- При отправке HTTP-запроса на вашу программу могут повлиять несколько факторов. Например, сервер, к которому вы отправляете запросы, может быть перегружен и медленно отвечать. Хотя ваш собственный код может быть производительным, вы зависите от всего, что находится вне вашего контроля, например от внешнего источника данных.
- Хотя здесь мы итерируем только пять аккаунтов, что, если мы создадим приложение, которому нужно будет итерировать более 500 или 5000 аккаунтов? Перебирать их один за другим было бы медленным, хотя и неизбежным процессом.
Это возможность для функции Salesforce взять на себя часть этой работы. Наш класс Apex может предоставить список учетных записей для обновления до функции Salesforce. Затем эта функция Salesforce может отправлять HTTP-запросы и обновлять учетные записи.
Прежде чем посмотреть, как может выглядеть полная миграция, давайте сначала напишем эту функцию Salesforce.
Разработка функции Salesforce
С помощью интерфейса командной строки sfdx мы можем легко создать новую функцию Salesforce в TypeScript a> с помощью одной команды:
$ sf generate function -n dogshowfunction -l typescript
Это создает набор файлов в разделе functions/dogshowfunction
. Наиболее важным из них является index.ts
, где будет находиться наш основной код функции Salesforce. Однако важны и другие файлы, связанные с тестированием и анализом кода, а также с определением генерации TypeScript и процесса развертывания Salesforce.
Давайте сосредоточимся на index.ts
. Вы заметите, что в этом файле экспортируется одна функция, и она принимает три параметра:
событие
. Описывает полезную нагрузку данных, поступающих из кода Apex.context
: содержит логику авторизации, необходимую для связи с Salesforce.регистратор
: это простой регистратор, который также интегрирует с Salesforce.
Код шаблона, создаваемый интерфейсом командной строки, показывает, насколько мощными являются функции Salesforce:
- Они могут принимать любые данные JSON, отправленные из Apex.
- Они могут работать напрямую с данными Salesforce.
- Они интегрируются напрямую с платформой таким образом, чтобы выполнять всю аутентификацию и безопасность за вас.
Лучше всего то, что, поскольку эта конкретная функция работает на Node.js, вы можете установить и использовать любой пакет NPM для дополнения своего кода. Давайте сделаем это прямо сейчас, установив node-fetch для выполнения нашего HTTP-запроса:
$ npm i node-fetch
Наша функция Salesforce будет отвечать за выдачу наших HTTP-запросов и обновление наших пяти учетных записей. Чтобы реализовать эту функциональность, наша функция может выглядеть примерно так:
export default async function execute(event: InvocationEvent<any>, context: Context, logger: Logger): Promise<RecordQueryResult> {
const accounts = event.data.accounts;
accounts.forEach(async (account) => {
const response = await fetch('https://dog.ceo/api/breeds/image/random');
const data = await response.json();
const message = ` And their favorite dog is ${data.message}`
const recordForUpdate = {
type: 'Account',
fields: {
id: account.id,
Description: `${account.Description} ${message}`
}
}
context.org.dataApi.updateRecord(recordForUpdate);
});
}
Давайте разберем, что происходит во фрагменте кода выше.
Наш аргумент события — это, по сути, объект JSON, который мы определим в нашем коде Apex. Хотя этот объект JSON еще не существует, мы можем предположить, что он будет иметь id
и Description
учетной записи, которую мы хотим обновить, основываясь на поведении нашего предыдущего Код вершины.
Отсюда важно отметить, что аргумент контекста по сути является реализацией Node.js SDK для функций Salesforce а>. Поскольку мы можем предположить, что эти данные учетной записи представлены в виде массива, мы можем просто перебирать каждый элемент, вставляя данные записи как часть нашей команды обновления.
Перенос кода Apex
Определив нашу функцию Salesforce, мы теперь можем заменить предыдущую логику Apex вызовом этой новой функции. Вызов функции Salesforce на удивление прост: нам нужно только знать имя нашей функции и предоставить данные, которые мы хотим отправить, как показано ниже:
public class Dogshow {
public static void updateAccounts() {
// Get the 5 oldest accounts
Account[] accounts = [SELECT Id, Description FROM Account ORDER BY CreatedDate ASC LIMIT 5];
// Set up the function
functions.Function dogshowFunction = functions.Function.get('ApexToSalesforceFunctionsMigration.dogshowfunction');
// Create a list to hold the record data
List<Map<String, String>> jsonObj = new List<Map<String, String>>();
for (Account account : accounts) {
Map<String, Object> obj = new Map<String, Object>();
obj.put('id', account.Id);
obj.put('Description', account.Description);
// Add an object to the record list
jsonObj.add(obj);
}
// Send the record list to the function
functions.FunctionInvocation invocation = dogshowFunction.invoke(JSON.Serialize(jsonObj));
// if the function had a return value, it would be available here
invocation.getResponse();
}
}
Именно так мы убрали длительную операцию из кода Apex и перенесли ее в функцию Salesforce. Теперь мы можем быть уверены, что наша операция будет продолжать работать, даже если она потребляет больше ресурсов.
Значение функций Salesforce невозможно переоценить. Благодаря функциям Salesforce, которые удовлетворяют наши потребности в длительных и ресурсоемких операциях, приложения, созданные на платформе Salesforce, теперь имеют гораздо больше возможностей для беспрепятственного масштабирования.
Заключение
Функции Salesforce позволяют оптимизировать рабочие процессы и создавать эффективные и надежные проекты. Без ограничений по памяти и ЦП, которые вы испытали бы в Apex, вы можете использовать функции Salesforce для выполнения длительных команд, обеспечивая масштабируемость без негативного влияния на производительность.
Мы только начали обсуждать потрясающие возможности Salesforce Functions. Чтобы узнать о них больше, Salesforce Functions предоставляет множество руководств с подробным описанием конкретных задач, а также различные рецепты Trailhead, на которые стоит обратить внимание.
Оригинал