<?php // Полная загрузка сервисных книжек, создан 2025-01-05 12:44:55
global $wpdb2;
global $failure;
global $file_hist;
///// echo '<H2><b>Старт загрузки</b></H2><br>';
$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
///// echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}
$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
///// echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}
/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
///// echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
///// echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist); ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7]; ////получаем размер файла
$m_mtime_file=$masiv_data_file[9]; ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file
///// echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
///// echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
///// echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);
if ($results)
{ foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));
////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
///// echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
///// echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}
////загружаем данные
$table='vin_history'; // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация // (путь от корня web-сервера)
$delim=';'; // Разделитель полей в CSV файле
$enclosed='"'; // Кавычки для содержимого полей
$escaped='\
На эту же темуhttp://infostart.ru/public/16486/
(1) Да, это тоже вариант. Но в моем варианте используется стандартный механизм фоновых заданий. Ком соединие используется только для того, чтобы выполнять задания, т.е. запускать стандартную функцию «выполнить задания».
Воттут пишут человек, что штатными способами вернуть результат работы невозможно из фонового задания. Для клиентсерверного варианта наверное действительно только через базу (хотя можно изучить возможность через временую таблицу).
Для файлового варианта, интуитивно чувствую что как-то можно через нотификации. Я просто немного запутался в них. Есть внешник, а есть внутренние, есть еще каие-то функции установки обработчиков. Что с чем стыкуется и какова «видимость» мне пока не ясно. Если есть кто на этом собаку съел поделитесь опытом.
Суть вопроса в следующем:
1. Как сгенерировать сообщение (событие, нотификацию) в 1С, которое передасться через ком соединение вызывающем приложению. Т.е. Чтобы его можно было поймать как в данном стандартном примере:
2. Как другим сопсобом сгенерить сообщение (например Notify — уведомить), чтобы как-то его отловить в другом сообщении.
(3) И вот еще как можно передать данные при данном варианте от отработавшего задания:
1. В глобальном модуле определяем переменную:
А потом в конце:
Плюс функция:
При выполнении фонового задания, фоновая функция должна знать свой ключ, т.е. его надо передавать ей параметром.
После выполнения функции перед конецфункции пишем:
РезультатыФоновойРаботы[Ключ] = <Наш результат работы в виде чего угодно>
И вуаля:
Запускаем фоновое задание. Отслеживаем его завершение через стандартный механизм: ФоновыеЗаданияПолучитьФоновыеЗадания или ФоновыеЗадания.НайтиПоУникальномуИдентификатору.
А затем обращаемся к наему глобальному ком объекту.
Рез = V8Com.ВернутьРезультатФоновогоЗадания(Ключ);
В данном случае это будет синхронный вызов и мы получим результат.
Мне кажется, что это элегантно.
Кстати, обычные фоновые задания довольно часто зависают. Решения проблемы так и не нашли — только перезапуск сервиса.
(5) Пока не сталкивался. А как виснут? В смысле виснет среда?
А что 1С по этому поводу говорит?
(6) В смысле то, что фоновое задание висит бесконечно со статусом «выполняется» и никак его не удалить, ни через консоль заданий, ни через консоль серверов, что в 8.1, что в 8.2 встречается. Поэтому и пришлось писать свою компоненту для многопоточности.
У у меня появился вопрос, получается будет запускаться еще одна копия 1с и следовательно должна быть еще одна свободная лицензия?
не понятно какой конкретно оператор запускает механизм выполнения заданий от имени сервера — ВыполнитьОбработкуЗаданий или оновыеЗадания.Выполнить ???
Спасибо автору за тему!
Очень нужная вещь, но…
Помогите плиз начинающему
Что куда вписывать? Платформа 8.2
Открыл конфигуратор, открыл модуль управляемого приложения
Сделал так:
Показать
Запускаю отладку и получаю ошибку
V8Com = Новый COMОбъект(«V81.Application»);
по причине:
Недопустимая строка с указанием класса
Попробовалэто — не помогло.
Подскажите, что я делаю не так?
Смущает «СтрокаСоединенияИнформационнойБазы» — может тут должно быть что-то более конкретное?
Требуется выполнять всего одно задание «обмен с сайтом», как-то в УТ10 это работало без дополнительной химии, а вот в УТ11 уже не получается.
(10)
Ответ очевиден:
Вопрос: метод работает, фоновые задания выполняются, НО необходимо фоновым заданием принудительно завершить работу пользователя в определенное время. Если запускал от имени текущего пользователя — все работало, но с этим методом вообще ничего не происходит. Может нашли уже какой-то способ передать сообщение о выполнении задания?
Уже не припомню.
Но как крайний вариант, сделайте так:
1. Создайте регистр сведений или используйте какой-то предопределенный элемент БД, который синхронизируется между разными потоками.
2. На клиентком процессе сделайе регулярный опрос ( каждый 30 сек например) этого регистра (или эл-та который вы использовали).
3. Если фоновый поток требует завершения пользователей,то в БД выставляется флаг (в этот ваш эл-т или регистр)
4. Клиентский поток смотрит это значение и если там стоит флаг завершения, то клиентский поток сам завершается по собственному т.с. желанию.
Если, я конечно правильно понял вашу задачу.
(12)Спасибо за ответ
Дело в том, что фоновый процесс нужен был, чтобы в файловом варианте не мешать работе пользователя постоянными проверками фоновых заданий. А то что вы предлагаете — значит опять проверять каждые 30 секунд на наличие флага) опять будут подвисания, тогда просто нет смысла в фоновом процессе… Или может я ошибаюсь, и есть способ проверять на наличие флага как-то незаметно?
P.S. Извините что не могу более ясно выражать мысли)) после работы голова гудит…
Я пробовал играться с нотификациями, но что-то не очень у меня это получилось.
У вас таймаут большой может быть (будет не критично) 30 сек или минута.
Там есть хэндлер (к сожалению уже не помню название) который может быть вызван только тогда когда нет активности на стороне пользователя. Если вы используете этот метод, то пользователь не будет замечать что система что-то опрашивает.
(0) отказался я от «COM-Объектов» и от ВыполнитьОбработкуЗаданий()
т.к. нужно было реализовать запуск независящий запуск от действий пользователя — пришлось использовать обработчики в ПриНачалеРаботыСистемы(), и порой на компе на котором это использовалось… плодились несколько COM-Объектов…. все работало и пользователю практически не мешало, но память съедалась(((
***************РЕШЕНИЕ — использовать ИСКЛЮЧИТЕЛЬНО «ФоновыеЗадания» а не их инициализацию через «РегламентныеЗадания» ****************
Показать
Здравствуйте! Подскажите, пожалуйста. Сталкивался кто-нибудь с такой проблемой, как «потеря пользователя» после выполнения фонового задания. Проверяю так:
МассивСоединений = ПолучитьСоединенияИнформационнойБазы();
Для Каждого ТекСоединение Из МассивСоединений Цикл
значение «ТекСоединение.Пользователь» именно текущего пользователя пустое.
Почему до выполнения фоновых заданий все норм, а после выполнения любого первого, как бы «теряется текущий пользователь»?