# Redis для 1С

> Redis для 1С

- GitHub: https://github.com/zerobig/redis-1c
- Gitsell page: https://gitsell.ru/zerobig/redis-1c
- Visibility: public/free
- GitHub stars: 11
- Gitsell views: 0
- Gitsell downloads: 0

## 1C Configurations

Not specified.

## Pricing

Free or price is not specified.

## README

# 1С Предприятие. Работа с сервером Redis

[![OpenYellow](https://openyellow.openintegrations.dev/data/badges/1184725125.svg)](https://openyellow.org/grid?filter=top&repo=1184725125)

## Мотивация

Потребовалось мне в одном проекте быстрое кэширование данных. Ну и понеслось...

## Описание

Библиотека предназначена для сохранения данных в БД Redis и, соответственно, для последующего получения этих данных.

Основной упор старался делать на скорость работы.

Библиотека написана с использованием внешней компоненты, которая реализует работу по протоколу TCP из 1С Предприятия. Компонента взята из проекта [OpenIntegrations](https://github.com/Bayselonarrend/OpenIntegrations). За что [Антона (Anton Titovets)](https://github.com/Bayselonarrend) сердечно благодарю.

### Реализованный функционал

* [x] Строки
* [x] Списки
* [x] Хэш-таблицы
* [x] Упорядоченные множества
* [x] JSON
* [x] Время жизни ключа
* [x] Транзакции
* [x] Некоторые общие функции

### В планах

* [ ] Множества
* [ ] Расширение возможностей для уже реализованных функций
* [ ] Примеры практического использования в конфигурациях
* [ ] Снижение режима совместимости платформы 1С Предприятия за счет отказа работы с регулярными выражениями
* [ ] Расширение документации
* [ ] Рассматриваю возможность работы с событиями:
  * Pub/Sub
  * Keyspace Notifications
  * Redis Streams

**Предуреждение!** Планы и другие доработки будут реализовываться в одном из двух случаев:

* при необходимости в данном функционале для моих разработок
* при активном участии (обратной связи) 1С сообщества

## Отличие от других проектов

* [1c-redis-lib](https://github.com/Daabramov/1c-redis-lib) - меня не устроили крайне малый набор функций и лицензия AGPL
* [redis-native-1c](https://github.com/tuplecats/redis-native-1c) - функций больше чем в предыдущем варианте, но всё равно достаточно ограниченное количество

Для обоих вариантов следует отдельно отменить что это внешние компоненты для 1С Предприятия. Т.е. если бы я захотел расширить их функционал, то мне пришлось бы писать на языке отличном от языка 1С Предприятия, затем компилировать библиотеку, отдельно беспокоиться о совместимости с Linux и вот это вот всё.

## Примеры использования

### Базовые функции

```bsl
// Параметры подключения к серверу Redis
ПараметрыПодключения = Новый Структура("Адрес, Пароль",
    "localhost:6379", "");

// Сохраняем значение в БД
Redis_ОсновныеФункции.УстановитьЗначение(ПараметрыПодключения,
    "НаименованиеОрганизации:000000001", "ООО ""СтройОптТорг""");

// Получаем значение из БД
НаименованиеОрганизации = Redis_ОсновныеФункции.ПолучитьЗначение(ПараметрыПодключения,
    "НаименованиеОрганизации:000000001");
Если НаименованиеОрганизации = Неопределено Тогда
    // Получаем значение из БД 1С
    ...
КонецЕсли;
```

### Работа с массивами (списками)

Сохранить и получить массив значений можно при помощи тех же функций которые описаны в разделе [Базовые функции](#базовые-функции). Но в случае получения значения при помощи базовой функции происходит на одно обращение к серверу Redis больше. Этот лишний вызов расходуется на проверку типа значения. Для уменьшения количества обращений можно использовать специализированные функции для каждого из типов данных:

```bsl
// Параметры подключения к серверу Redis
ПараметрыПодключения = Новый Структура("Адрес, Пароль",
    "localhost:6379", "");

МассивЦветовНоменклатуры = Новый Массив;
МассивЦветовНоменклатуры.Добавть("Белый");
МассивЦветовНоменклатуры.Добавть("Черный");
МассивЦветовНоменклатуры.Добавть("Баклажан");

// Сохраняем значение в БД
Redis_ОсновныеФункции.ДобавитьЭлементыВМассив(ПараметрыПодключения,
    "ДоступныеЦвета", МассивЦветовНоменклатуры);

// Получаем количество Элементов в списке Redis
КоличествоДоступныхЦветов = Redis_ОсновныеФункции.КоличествоСтрокМассива(ПараметрыПодключения,
    "ДоступныеЦвета");
Сообщить(КоличествоДоступныхЦветов);

// Получаем значение из БД
// Происходит на один вызов сервера меньше чем при использовании функции ПолучитьЗначение
МассивЦветовНоменклатуры = Redis_ОсновныеФункции.ПолучитьМассив(ПараметрыПодключения,
    "ДоступныеЦвета");
```

### Несколько последовательных действий

Создание соединения через внешнюю компоненту достаточно затратное по времени действие. Так что если перед вами стоит задача выполнить несколько последовательных действий с сервером Redis, то рекмендую один раз создать соединение и в дальнейшем использовать его при вызове функций:

```bsl
// Параметры подключения к серверу Redis
ПараметрыПодключения = Новый Структура("Адрес, Пароль",
    "localhost:6379", "");

// Создаём соединение
Соединение = Redis_ОсновныеФункции.ПолучитьСоединение(ПараметрыПодключения);
Если Соединение = Неопределено Тогда
    Возврат;
КонецЕсли;

// Сохраняем значения в цикле
Пока ВыборкаИзЗапроса.Следующий() Цикл
    Redis_ОсновныеФункции.УстановитьЗначение(Соединение,
        СтрШаблон("НаименованиеНоменклатуры:%1", ВыборкаИзЗапроса.Код),
        ВыборкаИзЗапроса.НаименованиеНоменклатуры);
КонецЦикла;

// Закрываем соединение после выполнения всех действий
Redis_ОсновныеФункции.ЗакрытьСоединение(Соединение);
```

### Работа с транзакцией

Транзакции в Redis это не совсем те транзакции которые есть в любой транзакционной БД. После начала транзакции сервер Redis ставит каждую последующую команду в очередь. И когда происходит фиксирование транзакции, то Redis просто выполняет все команды из этой очереди.

Важно понимать, что когда команда уже встала в очередь (то есть синтаксически верна), то, даже если она и вызовет ошибку при выполнении, остальные команды выполнятся всё равно. А вот если не встала (невалидна, вызвала ошибку при постановке в очередь), то Redis блок транзакции отклонит, даже не дождавшись завершения транзакции. И если вы попытаетесь после этого выполнить завершение транзакции, вам скажут, что транзакция была отклонена из-за предыдущих ошибок.

```bsl
// Параметры подключения к серверу Redis
ПараметрыПодключения = Новый Структура("Адрес, Пароль",
    "localhost:6379", "");

// Функция возвращает соединение с сервером которое следует использовать для дальнейшей
// постановки команд в очередь
Соединение = Redis_ОсновныеФункции.НачатьТранзакциюRedis();

// Сохраняем значения в цикле
Пока ВыборкаИзЗапроса.Следующий() Цикл
    Redis_ОсновныеФункции.УстановитьЗначение(Соединение,
        СтрШаблон("НаименованиеНоменклатуры:%1", ВыборкаИзЗапроса.Код),
        ВыборкаИзЗапроса.НаименованиеНоменклатуры);
КонецЦикла;

// Выполняем все команды которые были добавлены в очередь
Redis_ОсновныеФункции.ЗафиксироватьТранзакциюRedis(Соединение);
```

### Работа с временем жизни

Сервер Redis может самостоятельно удалять из своей базы записи с истекшим временем жизни. Значение срока через который запись будет автоматически удалена задаётся в секундах:

```bsl
// Параметры подключения к серверу Redis
ПараметрыПодключения = Новый Структура("Адрес, Пароль",
    "localhost:6379", "");

// Создаём соединение
Соединение = Redis_ОсновныеФункции.ПолучитьСоединение(ПараметрыПодключения);
Если Соединение = Неопределено Тогда
    Возврат;
КонецЕсли;

// Сохраняем значение в БД
Redis_ОсновныеФункции.УстановитьЗначение(Соединение,
    "НаименованиеОрганизации:000000001", "ООО ""СтройОптТорг""");

// Устанавливаем время жазни записи 1 час
Redis_ОсновныеФункции.УстановитьВремяЖизни(Соединение,
    "НаименованиеОрганизации:000000001", 60 * 60);

// Получаем оставшееся время жазни для записи
ОставшеесяВремя = Redis_ОсновныеФункции.ПолучитьВремяЖизни(Соединение,
    "НаименованиеОрганизации:000000001");
Сообщить(ОставшеесяВремя);

// Закрываем соединение после выполнения всех действий
Redis_ОсновныеФункции.ЗакрытьСоединение(Соединение);
```

## Документация

Документация находится по адресу [https://zerobig.github.io/redis-1c/](https://zerobig.github.io/redis-1c/). Наполнение продолжается.

## Тестирование

Тесты писались при помощи расширения для запуска тестов [YAxUnit](https://github.com/bia-technologies/yaxunit). И могут выполняться на пустой конфигурации 1С Предприятия

**Внимание!** YAxUnit для регулярных выражений использует внешнюю компоненту, так что требуется снять флаг безопасного режима. Иначе внешняя компонента не будет запущена.

## Лицензирование

Права на все использованные мной сторонние модули принадлежат авторам этих модулей.

Мой код распространяется с лицензией MIT.

## Благодарности

* [OpenIntegrations](https://github.com/Bayselonarrend/OpenIntegrations) - очень удачная внешняя компонента для работы с TCP из 1С Предприятия
* [YAxUnit](https://github.com/bia-technologies/yaxunit) - ребята, вы лучшие!