TLDR: в этой статье мы рассмотрим, как можно объединить шаблоны слоев и Temporal.io для эффективного управления рабочими процессами и действиями в приложениях Golang. Этот подход позволяет разделить бизнес-логику и функции доступа к данным, что приводит к более упорядоченной и модульной структуре кода. Мы предоставляем примеры кода и объясняем преимущества этого архитектурного стиля для более надежного и эффективного управления рабочим процессом, уменьшения количества ошибок и оптимизации процесса разработки.

В этой статье мы рассмотрим, как можно интегрировать шаблоны слоев и Temporal.io для создания эффективной оркестровки рабочего процесса для приложений Golang. Такой подход позволяет разделить бизнес-логику и функции доступа к данным, делая код более рациональным, модульным и удобным в сопровождении.

Многоуровневая архитектура

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

Структура:

main.go
config/
    config.go
repository/
    database.go
service/
    service.go
workflow/
    example_workflow.go
activity/
    example_activity.go
messages/
    example_messages.go

Файл main.go — это точка входа приложения. Он импортирует необходимые пакеты и запускает рабочий процесс.

Пакет конфигурации содержит файл config.go, который считывает значения конфигурации из файла или переменных среды для настройки приложения.

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

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

Пакет рабочего процесса содержит файл example_workflow.go, определяющий основную логику рабочего процесса для механизма Temporal.io.

Пакет активности содержит файл example_activity.go, который определяет логику активности, выполняемую движком Temporal.io.

Пакет сообщений содержит файл example_messages.go, который определяет сообщение и его типы.

Вот пример функций ExampleWorkflow и ExampleActivity на сайтах example_workflow.go и example_activity.go соответственно:

// example_workflow.go
func ExampleWorkflow(ctx workflow.Context) error {
    var data []string
    err := workflow.ExecuteActivity(ctx, ExampleActivity, "example").Get(ctx, &data)
    if err != nil {
        return err
    }

    // pass the data through the service layer
    service := NewExampleService()
    result, err := service.DoSomeComplexBusinessLogic(data)
    if err != nil {
        return err
    }

    // return the result to the caller
    return workflow.SetResult(ctx, result)
}
// example_activity.go
func ExampleActivity(ctx context.Context, input string) ([]string, error) {
    // Try to retrieve data 3 times with 2 seconds between each retry in case of any error
    retryOptions := temporal.RetryOptions{
        InitialInterval:        time.Second * 2,
        BackoffCoefficient:     2.0,
        MaximumAttempts:        3,
        DoNotRetry:             []error{ErrNonRetryable},
        NonRetryableErrorTypes: []reflect.Type{reflect.TypeOf(ErrNonRetryable)},
    }

    data, err := RetrieveDataFromDatabase(ctx, input)
    if err != nil {
        return nil, temporal.NewContinueAsNewError(ctx, ExampleActivity, input)
    }
    return data, nil
}
// database.go
func RetrieveDataFromDatabase(ctx context.Context, key string) ([]string, error) {
    // Use the repository to retrieve data from the database
    repo := NewExampleRepository()

    data, err := repo.GetDataFromDatabaseByKey(ctx, key)
    if err != nil {
        return nil, err
    }

    return data, nil
}

Эти функции демонстрируют, как многоуровневая архитектура работает с движком Temporal.io для управления рабочими процессами и действиями. Функция ExampleActivity повторяет попытку функции RetrieveDataFromDatabase в случае какой-либо ошибки с экспоненциальной задержкой и передает полученные данные через сервисный уровень для выполнения бизнес-логики. Когда бизнес-логика выполняется без ошибок, функция ExampleWorkflow использует механизм Temporal.io для установки результата рабочего процесса.

Структурируя приложение таким образом, мы можем разделить уровни доступа к данным и бизнес-логики, упрощая поддержку, управление и тестирование приложения.