Имя: Пароль:
1C
1С v8
Что делает "ПолучитьИзВременногоХранилища"
0 zelenprog
 
09.02.24
11:20
Здравствуйте!

Есть обработка.
Для ее работы нужно сохранить данные на сервере между серверными вызовами.
Первый вызов серверного метода формирует ("вычисляет") эти данные, следующие вызовы просто обращаются к ним и выполняют с ними некоторые действия.
Эти "серверные" данные представляют собой несколько ТаблицЗначений размером примерно по несколько тысяч строк (от 2-х до 5-и тыс. строк).

Как я понимаю, единственный способ для этого - это использовать "ПоместитьВоВременноеХранилище" и "ПолучитьИзВременногоХранилища".

Вопрос в том, насколько "трудоемким" является действие "ПолучитьИзВременногоХранилища"?
И что фактически делает эта функция? Как физически хранятся данные во временном хранилище?

Также интересует как лучше сохранять эти ТЗ во временном хранилище: (1) по отдельности или (2) все вместе?

(1) Можно сохранить каждую отдельную ТЗ в отдельном временном хранилище.
В этом случае при необходимости обратиться к конкретной ТЗ надо будет делать для каждой ТЗ "ПолучитьИзВременногоХранилища".

(2) А можно сделать структуру, состоящую из всех этих ТЗ, и поместить во времменное хранилище эту структуру.
В этом случае в серверном методе надо будет только один раз вызвать "ПолучитьИзВременногоХранилища", и дальше в коде обращаться к таблицам значений как:
лСтруктура.ТЗ1, лСтруктура.ТЗ2, ...

Будет ли разница по производительности между этими способами?
1 Галахад
 
гуру
09.02.24
11:24
Хм. А реквизита будет недостаточно?
2 zelenprog
 
09.02.24
11:28
(1) Реквизит передается туда-сюда с клиента на сервер.
Если эти таблицы значений делать реквизитами, то будут тормозить серверные вызовы. Так как 1С-ка будет автоматически "транслировать" изменения в этих таблицах между клиентом и сервером.
А эти таблицы значений чисто "служебные", они на клиенте не нужны, их не нужно передавать.

Для клиента формируется одна "сводная" ТЗ, которая и отображается на форме, она хранится в реквизите обработки.
3 Garykom
 
гуру
09.02.24
11:31
(0) Можно только в том случае если разные серверные вызовы с одной формы, которая между ними не закрывается

Синтаксис:
ПоместитьВоВременноеХранилище(<Данные>, <Адрес>)
Параметры:
<Данные> (обязательный)
Тип: Произвольный.
Данные, которые необходимо поместить во временное хранилище.
<Адрес> (необязательный)
Тип: УникальныйИдентификатор, Строка.
Уникальный идентификатор формы, во временное хранилище которой надо поместить данные и вернуть новый адрес. Или адрес во временном хранилище, по которому надо поместить данные. Адрес должен быть получен ранее с помощью данного метода.
В случае, если передается УникальныйИдентификатор формы или адрес в хранилище, то значение будет автоматически удалено после закрытия этой формы.
Если передан УникальныйИдентификатор, не являющийся уникальным идентификатором формы, то значение будет удалено после завершения сеанса пользователя.
Если передан адрес уже удаленного значения, будет сгенерировано исключение.
Если параметр не указан, помещенное значение будет удалено после очередного запроса сервера из общего модуля, при контекстном и неконтекстном серверном вызове из формы, при серверном вызове из модуля команды или при получении формы.
4 mikecool
 
09.02.24
11:32
главное с такими данными - не положить сервак
5 Garykom
 
гуру
09.02.24
11:33
Сначала на форме делаешь
Адрес = ПоместитьВоВременноеХранилище(Неопределено, ЭтаФорма.УникальныйИдентификатор);

Затем в серверные вызовы передаешь Адрес как параметр
6 Garykom
 
гуру
09.02.24
11:35
(0)
Вопрос в том, насколько "трудоемким" является действие "ПолучитьИзВременногоХранилища"?
И что фактически делает эта функция? Как физически хранятся данные во временном хранилище?

Ты не поверишь
Но физически временное хранилище - это просто временный файлик (в кэше) на диске сервера 1С
Поэтому если кластер серверов 1С (несколько их физических) то там бывают глюки если неправильно использовать
7 Builder
 
09.02.24
11:37
(0) Переделать серверные вызовы так, что бы не таскать данные через клиент, не предлагать?
8 zelenprog
 
09.02.24
11:44
(7) Конечно, предлагать.
Если есть более "правильный" способ - я только "за".
9 zelenprog
 
09.02.24
11:47
(5) >> Сначала на форме делаешь
Адрес = ПоместитьВоВременноеХранилище(Неопределено, ЭтаФорма.УникальныйИдентификатор);

В смысле - в клиентском методе?
10 Garykom
 
гуру
09.02.24
11:53
(9) можно и в клиентском
а можно в серверном первом/предварительном и сохранить адрес в реквизит формы
11 Garykom
 
гуру
09.02.24
11:54
в этом случае временное живет пока не закрыта форма
и потом после закрытия еще может некоторое время жить )) но уже не гарантируется
12 Garykom
 
гуру
09.02.24
11:56
Еще можно поступать по тупому через ПолучитьИмяВременногоФайла и сериализацию встроенную
Но это такое себе, особенно когда кластер
И можно забыть удалить
13 trad
 
09.02.24
12:00
// Все в модуле формы
&НаСервере
Функция РасчитатьИПоместитьДанныеНаСервере()

  ТЗ1 = ПосчитатьТЗ1НаСервере();
  ТЗ2 = ПосчитатьТЗ2НаСервере();
  Данные = Новый Структура("ТЗ1,ТЗ2", ТЗ1, ТЗ2);
  Адрес = ПоместитьВоВременноеХранилище(Данные, УникальныйИдентификатор);

  Возврат Адрес;

КонецФункции

&НаСервере
Процедура ЕщеОбработатьДанныеНаСервере(Адрес)

  Данные = ПолучитьИзВременногоХранилища(Адрес);
  Данные.ТЗ1.Свернуть(); //что-то делаем с ТЗ1
  Данные.ТЗ2.Свернуть(); //что-то делаем с ТЗ2

КонецПроцедуры

&НаКлиенте
Процедура Расчитать()

  АдресВРеквизитахФормы = РасчитатьИПоместитьДанныеНаСервере();

КонецПроцедуры

&НаКлиенте
Процедура ЕщеОбработать()

  ЕщеОбработатьДанныеНаСервере(АдресВРеквизитахФормы);

КонецПроцедуры
14 zelenprog
 
09.02.24
12:10
(13) Спасибо!
Именно так и задумывалось.

Теперь все-таки остается вопрос насчет трудозатратности.
Как долго выполняется "ПолучитьИзВременногоХранилища(Адрес)"?
Скорее всего, время выполнения зависит от объема сохраненных данных?
Чем больше строк в ТЗ, тем дольше она будет читаться из ВХ.
Так ведь?
15 Garykom
 
гуру
09.02.24
12:19
(14) На сервере достаточно быстро
Просто читает из кэша (с диска или даже из оперативки если ее много)
16 trad
 
09.02.24
12:39
ПоместитьВоВременноеХранилище - помещает ссылку на объект
ПолучитьИзВременногоХранилища - получает ссылку на объект
Поэтому, кмк, никаких затрат, до тех пор пока не потребуется передача сеансовых данных.
Но когда и как это происходит - я хз
17 zelenprog
 
09.02.24
12:57
(16) >> ПоместитьВоВременноеХранилище - помещает ссылку на объект
ПолучитьИзВременногоХранилища - получает ссылку на объект

Скорее всего, не саму ссылку, а данные.
То есть:
- "Поместить..." - помещает данные по ссылке в кеш.
- "Получить..." - получает данные (создает объект соответствующего типа и заполняет его данными и возвращает на него ссылку).

Верно?
18 Ёпрст
 
09.02.24
13:14
19 trad
 
09.02.24
13:18
(17)
ТЗ = ...
Адрес = ПоместитьВоВременноеХранилище(ТЗ, УникальныйИдентификатор);
ТЗ.Свернуть();

Что будет в хранилище?
20 trad
 
09.02.24
13:22
(18) http микросервис для решения (0)? Серьезно? ))
21 Ёпрст
 
09.02.24
13:30
(20) ну, мот он туда >4гигов запихать хочет
22 Garykom
 
гуру
09.02.24
13:31
(20) Фактически при передаче клиент-сервер файлов от 1 гига начинаются проблемы
Они банально портятся
23 zelenprog
 
09.02.24
13:43
(17) Свернутая ТЗ.
Видимо 1С-ка сама отслеживает изменения в объектах и сразу же обновляет временное хранилище новыми данными.
24 zelenprog
 
09.02.24
13:43
(19) Свернутая ТЗ.
Видимо 1С-ка сама отслеживает изменения в объектах и сразу же обновляет временное хранилище новыми данными.
25 zelenprog
 
09.02.24
13:46
(18), (20), (21), (22)
В моем случае "ПоместитьВоВременноеХранилище" вызывается на сервере. Так что проблемы с передачей данных с клиента на сервер нету.
26 Garykom
 
гуру
09.02.24
14:09
(19) >Что будет в хранилище?

ссылка на ТЗ :)
27 trad
 
09.02.24
14:34
(23) ничего не отслеживает и не обновляет. Просто ссылку хранит
(26) да, поэтому, получив из хранилища, будем иметь дело со свернутой ТЗ, хотя свернули ее после помещения в хранилище
28 zelenprog
 
09.02.24
14:42
(26),(27) А где же тогда сохраняются данные после выхода из серверного вызова и до следующего серверного вызова?
29 Garykom
 
гуру
09.02.24
14:49
(28) Есть такое понятие счетчик ссылок
Пока ссылка на некий объект используется - объект из памяти (в данном случае сервера 1С) не чистится
30 zelenprog
 
09.02.24
14:58
(29) Если серверный вызов завершился, то счетчики на все используемые в нем ссылки обнуляются. Значит, такие ссылки должны быть очищены из памяти.
Но при следующем вызове серверного метода, данные после "ПолучитьИзВременногоХранилища" восстанавливаются.
Значит, во временном хранилище хранится не только ссылка, но и сами данные.
31 TormozIT
 
гуру
10.02.24
00:08
(30) Счетчики ссылок только увеличиваются и уменьшаются при уничтожении переменных и объектов, их содержащих. Когда серверный вызов завершается, то просто уничтожаются все переменные корневого вызванного на сервере метода. Если в памяти остался объект из кольца/цикла ссылающихся объектов, то все участники кольца остаются в памяти.

Метод ПоместитьВоВременноеХранилище() сразу отправляет данные в менеджер кластера (сервис сеансовых данных), но оставляет копию этих данных в памяти серверного процесса (в кэше).

Метод ПолучитьИзВременногоХранилища() очень похож на функцию общего модуля с повторным использованием возвращаемых значений. Пока в памяти есть копия объекта из временного хранилища, он возвращает ее, т.е. не обращается к менеджеру кластера. Эта копия объекта живет по правилам выше упомянутого кэша методов общих модулей, т.е. например через 6 минут после последнего обращения очищается и при следующем обращении будет получаться заново из менеджера кластера.

Если поместить большую таблицу значений во временное хранилище и затем регулярно к ней обращаться на чтение/запись, то она будет вести себя как обычный объект в памяти процесса. Но не будет отправляться в менеджер кластера, т.е. если пройдут 6 минут без обращений к измененной и не отправленной во временное хранилище таблица, то эти изменения пропадут.
32 ProxyInspector
 
10.02.24
18:09
А временное Хранилище - это не файл на диске случайно?
33 Garykom
 
гуру
10.02.24
18:37
(32) почему случайно? как раз совсем не случайно
34 ДедМорроз
 
10.02.24
19:30
Временное хранилище это блок в файле в директории хранилища кластера - сериализация там такая же как и при передаче с сервера на клиента (ну мы же помним,что передаются только таблицы в реквизитах формы)
35 Garykom
 
гуру
10.02.24
20:25
(34) Там от типа данных зависит
Для ДвоичныеДанные пишет в отдельные файлы
Возможно еще от объема зависит конечно
В экспериментах когда большие файлы помещал они в отдельные сохранялись на сервере
Но в разных версиях платформы может быть по разному
36 ProxyInspector
 
10.02.24
23:07
Это же ЦИРК. Передавать параметры между процедурами программы через файл на диске.
37 Garykom
 
гуру
10.02.24
23:13
(36) Ты думаешь одна программа?
Тонкий клиент 1С запускается на одном компе
Сервер 1С на другом компе
И учти что процессов сервера несколько!
Причем процесс который исполняет серверный код не обязательно тот же что держит связь с клиентом
38 ДедМорроз
 
11.02.24
03:15
(35) там зависит только от объема данных,а не от типа.
Насколько я помню, размер одного файла 64 Мб.
Новый блок пишется в конец файла,все,что освободили,остаётся в файле до выполнения сжатия,когда занятые блоки переносятся в другие файлы.
По сути - это специализированная Key-Value база данных.
39 breezee
 
12.02.24
06:38
2-5 к строк фигня. Вы там на калькуляторе сервер держите, что ли?
40 zelenprog
 
12.02.24
09:03
(31) >> Если поместить большую таблицу значений во временное хранилище и затем регулярно к ней обращаться на чтение/запись, то она будет вести себя как обычный объект в памяти процесса. Но не будет отправляться в менеджер кластера, т.е. если пройдут 6 минут без обращений к измененной и не отправленной во временное хранилище таблица, то эти изменения пропадут.

Хм...
Получается, для надежности, надо обязательно выполнять "ПоместитьВоВременноеХранилище" при каждом возврате из серверного вызова, если в этом вызове были сделаны изменения в ТЗ?

Ведь неизвестно какой промежуток времени пройдет между серверными вызовами. Серверный вызов происходит при выполнении пользователем какой-либо команды. А сколько пройдет времени между этими командами зависит только от самого пользователя. Может он пойдет чайку попить минут на 20, оставив открытым 1С и форму обработки.

Если "ПоместитьВоВременноеХранилище" сделать только один раз для ТЗ (например только при первом заполнении ТЗ), то по вашим словам, за время чаепития изменения в кеше будут очищены. И когда пользователь захочет после перерыва выполнить какую-то команду, то при новом вызове серверного метода произойдет чтение данных из менеджера кластера, которые будут без изменений. Правильно я понимаю?
41 zelenprog
 
12.02.24
11:57
(19)
>> ТЗ = ...
>> Адрес = ПоместитьВоВременноеХранилище(ТЗ, УникальныйИдентификатор);
>> ТЗ.Свернуть();

Что будет в хранилище?

(24), (26), (27)
>> получив из хранилища, будем иметь дело со свернутой ТЗ, хотя свернули ее после помещения в хранилище

Получается это не верно.
Согласно (31) в хранилище не попадет свернутая ТЗ, она будет только в кеше.
42 trad
 
12.02.24
12:08
(41) а твои эксперименты что показывают?
43 H A D G E H O G s
 
12.02.24
12:30
(40) "Получается, для надежности, надо обязательно выполнять "ПоместитьВоВременноеХранилище" "

Да. На 50000 строк ты это отлично почувствуешь.
44 zelenprog
 
12.02.24
12:53
(43) >> Да. На 50000 строк ты это отлично почувствуешь.

Что ты имеешь ввиду? Что будет тормозить?
Так ведь выхода другого нету.

Хотя... Может быть есть какой-то другой более правильный способ решения этой проблемы?

То есть проблема в следующем.
Нужно, чтобы общий серверный модуль представлял собой некий "объект", который имеет свое состояние и "внутренние" данные.
Чтобы разные методы этого общего модуля, вызываемые из клиентских методов формы в разное время работы клиентской обработки, использовали эти "внутренние" данные.
45 Garykom
 
гуру
12.02.24
12:57
(44) Тебе что мешает каждый раз в серверном коде ПолучитьИзВременногоХранилища(), обрабатывать и снова использовать ПоместитьВоВременноеХранилище()?
46 H A D G E H O G s
 
12.02.24
13:27
(44) Нет. Ничего не тормозит. Просто если ты большие данные при повторном помещении не будешь фиксировать через ПоместитьВоВременноеХранилище - ты их потеряешь.
47 lodger
 
12.02.24
14:36
(44) ну вот и сделай РС (ну или справочник\документ с ТЧ), куда ты будешь заливать и записывать свои строки в процессе расчётов. заодно появится возможность не считать одно и то же 2 раза даже спустя месяц.
48 ilya_i
 
12.02.24
14:57
Делал фоновое вычисление и возвращал через ВременноеХранилище , был очень плохой эффект, когда фонка завершается, но во временном хранилище всё ещё ничего нет, пауза доходила до 8 секунд даже на данных смешного размера.
49 ilya_i
 
12.02.24
15:00
Получал на клиенте, всё по учебнику, но проходило несколько секунд прежде чем в хранилище появлялось значение, приходилось подвешивать обработчик ожидания и раз в пару секунд проверять, а не появилось ли там значение.
50 zelenprog
 
12.02.24
15:14
(45) >> Тебе что мешает каждый раз в серверном коде ... обрабатывать и снова использовать ПоместитьВоВременноеХранилище()?

Некоторые серверные методы не меняют эти данные, а просто их используют. Если каждый раз при этом делать "ПоместитьВоВременноеХранилище()", то мне кажется тормозить будет.

Ну, например на форме обработки есть кнопка "Показать контрагента". По этой кнопке надо по рассчитанным серверным данным по определенной логике найти контрагента и просто показать его.
Если при этом еще и выполнить "ПоместитьВоВременноеХранилище()", то думаю что задержка будет заметна.

Если же "ПоместитьВоВременноеХранилище()" делать при возврате из серверного метода не всегда, а только тогда когда есть изменения в данных, то придется как-то отслеживать были ли сделаны изменения.
"Главный" серверный метод вызывает другие серверные методы. Получается надо во все методы добавлять параметр, который будет возвращать признак что-то типа "ДанныеИзменены". И если этот признак = Истина, только в этом случае делать "ПоместитьВоВременноеХранилище()".
Как-то сложно получается.
51 zelenprog
 
12.02.24
15:16
(46) >> Нет. Ничего не тормозит.

Как это не тормозит?
Каждый раз при возврате из серверного метода делать "ПоместитьВоВременноеХранилище()" для таблицы значений 50 тыс. строк - и это не будет тормозить?
52 JanK
 
12.02.24
15:31
(0)

>Вопрос в том, насколько "трудоемким" является действие "ПолучитьИзВременногоХранилища"?

Зависит от объёма помещаемых данных.


>И что фактически делает эта функция?

1. Условно - создаёт запрос на помещение данных в хранилище сеансовых данных (в кластере)
2. По окончании серверного вызова
2.1 Данные сериализуются (тем же способом что при засовывании в ХранилищеЗначения/ЗначениеВСтрокуВнутр) 2.2 Результат отправляется в (кластерный) сервис сеансовых данных

При этом:
а) Если что-то нельзя было сериализовать (например ДокументОбъект в поле структуры) ошибка не выдаётся, но обратно вернётся Неопределено
б) Данные остаются в сеансовом кеше рабочего процесса, так что ПолучитьИзВременногоХранилища до переезда сеанса в другой рабочий процесс / очистки сеансового кеша не будет приводить к фактическуму получению (и десериализации) данных из сервиса


>Как физически хранятся данные во временном хранилище?

С точки зрения пользователя механизма - можно считать что одним куском. Расположены - на диске в сервисе сеансовых данных, там же в памяти + в сеансовым кеше рабочего процесса, в котором размещён сеанс.
53 TormozIT
 
гуру
12.02.24
15:32
(50) Если часто делать ПоместитьВоВременноеХранилище(), то программа будет работать очень медленно при большом объеме данных во временном хранилище. Поэтому помещать данные во временное хранилище нужно раз в 5 минут через обработчик ожидания, т.к. через 6 минут они уже могут быть удалены из кэша процесса.
54 TormozIT
 
гуру
12.02.24
15:34
(53) Конечно это все в контексте понимания, что редкая потеря этих данных (например при переезде сеанса в другой рабочий процесс) не сильно расстроит пользователя.
55 zelenprog
 
13.02.24
12:11
(54) Потеря этих данных приведет к неработоспособности обработки. Данные должны существовать все время пока пользователь пользуется обработкой.

Может быть правда подумать об использовании Регистра?
Какие могут есть недостатки в использовании регистра вместо временного хранилища?
56 Garykom
 
гуру
13.02.24
13:08
(55) если у тебя много строк в ТЗ - то совершенно логично их между вызовами сохранять в своем РС
причем с привязкой к уникальному УИД сеанса
57 Garykom
 
гуру
13.02.24
13:09
(56)+ Хотя имхо можно прекрасно обойтись МВТ с нужными ВТ внутри ))
58 Garykom
 
гуру
13.02.24
13:24
(57)+ Естественно если разные серверные вызовы с одним МВТ в рамках одного сеанса 1С
Если же и сеансы 1С разные - пиши в РС
https://infostart.ru/1c/articles/1217577/
59 TormozIT
 
гуру
13.02.24
16:39
(58) Менеджер временных таблиц запрещено удерживать в кэше на сервере между серверными вызовами. Платформа это теперь даже сама проверяет и ругается понятно. В статье по твоей ссылке про это тоже рассказано.
60 Garykom
 
гуру
13.02.24
16:44
(59) Из одного сеанса пользователя вроде можно
Из разных понятно нельзя
61 Garykom
 
гуру
13.02.24
16:49
(60)+ Стандартная ситуация, запускается фоновое, создает МВТ и порождает другое фоновое с тем же МВТ, дожидается завершения и еще обработка
62 TormozIT
 
гуру
13.02.24
20:15
(61) Ты фантазируешь. Реальность устроена как я описал и как написано в статье, которую ты получается не читал.
63 Garykom
 
гуру
13.02.24
20:34
(62) Кто/что запретит длительному фоновому заданию крутиться долго на сервере?
Держа МВТ и в цикле отрабатывая запросы?

Тексты запросов и параметры через временное хранилище.

Результат можно выборочно получать из ВТ, так же через временное хранилище.
64 Garykom
 
гуру
13.02.24
20:55
(63)+ Хотя с временным хранилищем обмен между длительным фоновым и клиентом/сервером засады есть
Придется извращаться как то, например через РС заданий на обработку с текстами запросов
65 ДедМорроз
 
13.02.24
21:19
Обмена через временное хранилище между фоновым заданием и другим процессом просто нет.
Есть передача результата фонового задания в контекст родительского процесса при его завершении.
66 Garykom
 
гуру
13.02.24
21:22
(65) Угу
Поэтому придется извращаться для периодического двухстороннего обмена между длительным фоновым и клиентом/сервером

Например РС или внешний микросервис
В платформе кстати анонсированы сообщения (оповещения) с сервера на клиент - потом можно будет заюзать
67 NorthWind
 
13.02.24
22:13
(36) почему? Это просто 1С сделала серверные вызовы прозрачными для программиста, как вызовы прочих функций/процедур. Но на самом деле ежу ведь понятно, что это не то же самое что вызовы локальных клиенских. Под капотом происходят совершенно другие вещи с другими накладными расходами. И да, временные файлы там могут быть, ничего странного в этом нет если тебе нужно передавать что-то большое на другую машину. Вон у браузеров сотни мегов кэша бывает и ниче, никого это не парит. Так надо.