Программное создание джобов
На страницу 1, 2, 3, 4 След.
|
Предыдущая тема :: Следующая тема |
Автор |
Сообщение |
nataly Участник со стажем
Вступление в Клуб: 22.07.2011
|
Пн Сен 12, 2011 18:06  Программное создание джобов |
|
Полезность: Нет оценки
|
Киньте плиз примерчик - создать джоб, выполнить, удалить |
|
 |
Random Эксперт
Вступление в Клуб: 27.06.2011
|
Вт Сен 13, 2011 05:34   |
|
Полезность: 1
|
Код: | declare -- для Oracle младше 10g не использовать dbms_utility.format_error_backtrace
v$info rtl.debug_rec;
-- Функция запуска задания Oracle немедленно (на самом деле через неск.сек).
function BackRun(p_ex varchar2) return number is
v$job integer;
v$interval varchar2(2000);-- интервал null - т.е. не повторяется
begin
dbms_job.submit(v$job, p_ex, sysdate, v$interval, false);
commit;
return v$job;
end;
begin
-- Регистрируемся
dbms_output.put_line(rtl.open);
-- Именуем монитор канала - для теста
rtl.set_debug_pipe('test');
-- Получаем информацию о названии монитора канала
rtl.get_debug_all(v$info);
-- запускаем задание
debug_pipe('номер задания оракла:'||BackRun(
'declare n integer;
begin
-- Регистрируемся в джобе, чтобы можно было выполнять операции модели данных ЦФТ-Банк
n := executor.lock_open(''JOB'', job);
-- устанавливаем имя канала
rtl.set_debug_pipe('''||v$info.debug_pipe_name||''');
-- Ломаем джоб, чтобы в случае если сессию кильнут или она сломается, джеб не перезапустился снова
-- удалять нельзя, иначе к операциям модели данных нельзя будет обратиться - сломаются
dbms_job.broken(job, true);
-- Что-то делаем
rtl.debug_pipe(''я уже работаю!'',0);
-- самоудаляемся
begin
dbms_job.remove(job);
commit;
exception when others then
rtl.debug_pipe(dbms_utility.format_error_backtrace,0);
end;
rtl.close;
exception when others then
begin
dbms_job.remove(job);
commit;
exception when others then
rtl.debug_pipe(dbms_utility.format_error_backtrace,0);
end;
rtl.close;
end;'
),0);
end; |
|
|
 |
maestro Профи
Вступление в Клуб: 12.10.2010
|
Вт Сен 13, 2011 09:07   |
|
Полезность: Нет оценки
|
Выполнить поиск по текстам по ключевому слову [TEXT_JOBS]. Найдете массу примеров. |
|
 |
Random Эксперт
Вступление в Клуб: 27.06.2011
|
Вт Сен 13, 2011 09:21   |
|
Полезность: Нет оценки
|
А, да.
Есть еще Система [SYSTEM] -> Выполнение заданий по расписанию  |
|
 |
nataly Участник со стажем
Вступление в Клуб: 22.07.2011
|
Ср Сен 14, 2011 16:11   |
|
Полезность: Нет оценки
|
по текстам - это по таблице source ? |
|
 |
nataly Участник со стажем
Вступление в Клуб: 22.07.2011
|
Ср Сен 14, 2011 16:14   |
|
Полезность: Нет оценки
|
Спасибо за приме6рчик, много полезного для меня, но интересует именно PL\Plus |
|
 |
nataly Участник со стажем
Вступление в Клуб: 22.07.2011
|
Ср Сен 14, 2011 16:34   |
|
Полезность: Нет оценки
|
nataly пишет: | по текстам - это по таблице source ? |
ничего реализующего обычный запуск ораклевого джоба не нашла.
ненавижу pl\plus )) |
|
 |
maestro Профи
Вступление в Клуб: 12.10.2010
|
Чт Сен 15, 2011 09:25   |
|
Полезность: Нет оценки
|
nataly пишет: | по текстам - это по таблице source ? |
А администраторе словаря с галкой "Операций" в блоке "Просматривать тексты"
nataly пишет: |
ненавижу pl\plus )) |
Зря. А мы его любим
копипаст первого попавшегося примера из дистрибутивной операции WORK_DEPR
[code]procedure startCalcJob(pDoc ref [TMC_DOCUM], pGroup ref [TMC_GRUP], pHDpt ref [DEPART],/*pFinProv boolean,*/ pDateWork date, pJobIds in out rtl.number_table, p_sign_no_in_out in boolean)
is
vJobObj [TEXT_JOBS];
vJobRef ref [TEXT_JOBS];
vErrStr varchar2(4000);
V_LOG_DIR varchar2(300) := [FP_TUNE]::[LIB].get_str_value('EOD_LOG_DIR',0);
begin
vJobObj%id := next_value('SEQ_ID');
vJobObj.[PLPLUS] :=' PRAGMA INCLUDE ([RUNTIME].[MACRO_LIB]);'||LF$
||' declare'||LF$
||' vJob ref [TEXT_JOBS];'||LF$
||' begin'||LF$
||' vJob := '|| vJobObj%id||';'||LF$
||' set_debug_file('''||V_LOG_DIR||to_char(sysdate,'yymmdd')||'_'||replace(pGroup.[CODE], ' ', '_') || '.log'');'||LF$
||' ::[TMC_DOCUM].[WORK_DEPR].startCalcProcess('
||' '||pDoc%id||LF$
||' ,'||pGroup%id||LF$
||' ,'||nvl( to_char( pHDpt%id ), 'null' )||LF$
||' ,'||' to_date('''||to_char(pDateWork, 'dd/mm/yyyy')||''', ''dd/mm/yyyy'')'||LF$
||' ,'||vJobObj%id||LF$
||' ,'''||bool_char(p_sign_no_in_out) || ''''||LF$
||' );'||LF$
--vCode := vCode|| ' commit;' || nl$;
||' exception when others all then '||LF$
||'null;' || LF$
--||' ::[TEXT_JOBS].[APP_LIB].del_job(vJob);' || LF$
--vCode := vCode|| ' commit;' || nl$;
||' end;'||LF$;
------------------------------------------------------------
vJobObj.[NAME] := 'Расчет амортизации по группе ТМЦ с кодом "' || pGroup.[code] || '" для документа '||pDoc%id||' дата обработки '||to_char(pDateWork, 'DD/MM/YY');
vJobObj.[METHOD_CLASS] := 'TMC_DOCUM';
vJobObj.[SHORT_NAME] := 'c_' || rtl.next_value('SEQ_ID');
vJobObj.[FIRST_TIME] := null;
vJobObj.[STATUS] := [TEXT_JOBS]::[EDIT_AUTO].parse_plplus(vJobObj.[PLPLUS], vErrStr, vJobObj.[PLSQL]);
if vJobObj.[STATUS]='PROCESSED' then
vJobObj.[STATUS] := [TEXT_JOBS]::[EDIT_AUTO].parse_plsql(vJobObj.[PLSQL], vErrStr);
else
pragma error('Ошибка генерации исполняемого кода: ' || vErrStr || nl$ || 'Текст plplus: ' || nl$ || vJobObj.[PLPLUS]);
end if;
if vJobObj.[STATUS]!='VALID' then
pragma error('Ошибка генерации исполняемого кода: ' || vErrStr || nl$ || 'Текст pl/sql: ' || nl$ || vJobObj.[PLSQL]);
end if;
vJobObj%id := ::[TEXT_JOBS]%insert(vJobObj, vJobObj%id);
vJobRef := vJobObj%id;
vJobRef.[ADD_JOB];
vJobRef.[SUBMIT_JOB](null, null,null,null);
rules.set_object_rights(::[TEXT_JOBS]%class, vJobObj%id, 'NEW');
commit;
pJobIds(pJobIds.count + 1) := vJobRef%id;
end;[/code] |
|
 |
Random Эксперт
Вступление в Клуб: 27.06.2011
|
Чт Сен 15, 2011 10:51   |
|
Полезность: 1
|
nataly пишет: | Спасибо за приме6рчик, много полезного для меня, но интересует именно PL\Plus |
Хорошо, на pl/+ первой строчкой напиши
Код: | pragma pl_sql(true);-- включить расширенный синтаксис
-- остальное почти то же самое
-- для Oracle младше 10g не использовать dbms_utility.format_error_backtrace
-- Функция запуска задания Oracle немедленно (на самом деле через неск.сек).
function BackRun(p_ex varchar2) return number is
v$job integer;
v$interval varchar2(2000);-- интервал null - т.е. не повторяется
begin
dbms_job.submit(v$job, p_ex, sysdate, v$interval, false);
commit;
return v$job;
end;
procedure start_job(p_run varchar2) is
begin
-- Регистрируемся
-- dbms_output.put_line(rtl.open);--регистрация в pl/+ не нужна
-- Именуем монитор канала - для теста
-- rtl.set_debug_pipe('test');-- тоже не надо, канал уже поименован
-- Получаем информацию о названии монитора канала
get_debug_all(v$info);-- убрали название пакета rtl - само появится
-- запускаем задание
debug_pipe('номер задания оракла:'||BackRun(
-- а вот здесь все должно быть на pl/sql!!!!!!!
'declare n integer;
begin
-- Регистрируемся в джобе, чтобы можно было выполнять операции модели данных ЦФТ-Банк
n := executor.lock_open(''JOB'', job);
-- устанавливаем имя канала
rtl.set_debug_pipe('''||v$info.debug_pipe_name||''');
-- Ломаем джоб, чтобы в случае если сессию кильнут или она сломается, джеб не перезапустился снова
-- удалять нельзя, иначе к операциям модели данных нельзя будет обратиться - сломаются
dbms_job.broken(job, true);
-- Что-то делаем
rtl.debug_pipe(''я уже работаю!'',0);
'||p_run||'
-- самоудаляемся
begin
dbms_job.remove(job);
commit;
exception when others then
rtl.debug_pipe(dbms_utility.format_error_backtrace,0);
end;
rtl.close;
exception when others then
begin
dbms_job.remove(job);
commit;
exception when others then
rtl.debug_pipe(dbms_utility.format_error_backtrace,0);
end;
rtl.close;
end;'
),0);
end;
|
Или тебе необходимо, чтобы текст, написанный на pl/+ выполнялся?
В таком случае могу посоветовать функцию PlusEXr:
Код: |
function ParsePlPlus(p_text varchar2) return varchar2 is
m_plsql varchar2(32767);
m_errors varchar2(32767);
begin
m_plsql := p_text;
-- Уж и не знаю, почему эта процедурка так называется...
-- но она парсит pl/+ -текст, а большего от нее и не надо
if (method.generate_view(m_plsql, m_errors) > 0) then
m_plsql := m_errors;
end if;
return m_plsql;
end;
function PlusEXr(p_ex varchar2) return varchar2 is
tr varchar2(32767);
v$ret varchar2(32767);
begin
tr := '-- begin pl/plus'||LF$
||'function ddd return varchar2 is '
||'begin '||p_ex||' end;-- end pl/plus'||LF$;
tr := ParsePlPlus(tr);
tr := 'declare '||tr||'begin :res:= ddd; end;';
if rtl.exec_sql_out(tr,'res',v$ret) <> 0 then
pragma error('Ошибка при выполнении динамического блока в функции PlusEXr');
end if;
return v$ret;
end;
...
-- тут вставляем предыдущий пример с корректировкой:
-- Что-то делаем
rtl.debug_pipe(''я уже работаю!'',0);
'||PlusEXr(p_run)||'
-- самоудаляемся
|
Последний раз редактировалось: Random (Чт Сен 15, 2011 11:08), всего редактировалось 4 раз(а) |
|
 |
Random Эксперт
Вступление в Клуб: 27.06.2011
|
Чт Сен 15, 2011 10:59   |
|
Полезность: Нет оценки
|
nataly пишет: | по текстам - это по таблице source ? |
Ну вообще-то да, хотя лучше искать с помощью функции поиска из АРМ Администратор словаря данных |
|
 |
Random Эксперт
Вступление в Клуб: 27.06.2011
|
Чт Сен 15, 2011 11:17   |
|
Полезность: Нет оценки
|
maestro пишет: | копипаст первого попавшегося примера из дистрибутивной операции WORK_DEPR |
Я прошу прощения, но вот тут - создание новой операции, а потом ее запуск:
maestro пишет: |
Код: |
vJobObj.[METHOD_CLASS] := 'TMC_DOCUM';
vJobObj.[SHORT_NAME] := 'c_' || rtl.next_value('SEQ_ID');
|
|
По-моему, это из пушки по воробьям
Задача гораздо проще.
Тем более, что если такое сделать у себя, ЦФТ за это по голове не погладит. Как говорится, что позволено Зевсу, не позволено остальным. Для прочих смертных есть спец.пакет RUNTIME.PLP_TOOLS - глянь, тоже много интересного. |
|
 |
nataly Участник со стажем
Вступление в Клуб: 22.07.2011
|
Чт Сен 15, 2011 16:17   |
|
Полезность: Нет оценки
|
Спасибо! Джобы с божьей... форумской помощью посоздавала и позапускала. И даже нашла как их удалить.
Следующий вопрос, а вот как бы остановить и удалить по проверке из того же или внешнего модуля, например один из нескольких джобов у меня сбойнул, я отловила этот факт по failure и хочу убить и удалить все остальные |
|
 |
Random Эксперт
Вступление в Клуб: 27.06.2011
|
Пт Сен 16, 2011 09:52   |
|
Полезность: Нет оценки
|
nataly пишет: | Спасибо! Джобы с божьей... форумской помощью посоздавала и позапускала. И даже нашла как их удалить.
Следующий вопрос, а вот как бы остановить и удалить по проверке из того же или внешнего модуля, например один из нескольких джобов у меня сбойнул, я отловила этот факт по failure и хочу убить и удалить все остальные |
Лучше не по failures, а по broken
Код: | select u(count(1)) in user_jobs%rowtype
where (u.[job] = p_job or u.[what] = p_what) and (u.[broken] = 'Y' or u.[failures] > 4) |
Удалить джоб, можно с помощью dbms_job.remove. Остановить (сломать) - dbms_job.broken(true);. А чтобы убить работающую сессию этого джоба, используй
Код: | for ( select x(v.sid:sid, v.serial#:serial) in user_jobs%rowtype, (v$session%rowtype :v)
where x.[CLIENT_INFO] = ''||x.[job]) loop
method.kill_session(x.sid||','||x.serial);
end loop; |
В общем, разберешься
Собственно, method.kill_session это вызов процедуры kill_session, вот только вызвать из pl/+-операции процедуру без pl/sql-вставок или execute immediate у меня не получилось |
|
 |
nataly Участник со стажем
Вступление в Клуб: 22.07.2011
|
Пт Сен 16, 2011 15:09   |
|
Полезность: Нет оценки
|
Посмотрите свежим взглядом, что где проср...не учла
Задача - распаралелливание формирования отчета. Тренируюсь на Депозитном портфеле как самом простом в этом плане
Использую джобы, каждый из которых обрабатывает свой диапазон данных.
В отчетной форме в секции Проверка запускается N джобов, каждый из которых после успешного завершения самоликвидируется
В секции Тело идет проверка состояний джобов, если все успешно выполнились и самоликвидировались, то типа отчет выполнен, радостно выходим. Если попался сбойный по признаку FAILURES>1, то форма выдает ошибку, типа сори, сбойнула, почистите пож уже сформированные неполные данные ручками и удалите умершие и живые джобы.
Это на текущий момент. Хотелось бы: в случае обнаружения сбойнувшего джоба, отчетик тормозит и удаляет и сбойнутый и выполняемый, и ощищает саму таблицу от того, что успело отработать и успешно туда записаться.
А вот на что сориентироваться, в случаях когда
1- сессия убита
2- джоб убит
3- джоб убит из интерфеса
4 - джоб получил ошибку
Рвботает только в последнем случае, как вычислить предыдущие пока не соображу |
|
 |
nataly Участник со стажем
Вступление в Клуб: 22.07.2011
|
Пт Сен 16, 2011 15:12   |
|
Полезность: Нет оценки
|
т.е. я поубивала нафиг все джобы, а z$system|_job и z#text_job этого не видят, у них типа все работает... |
|
 |
|
|
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете голосовать в опросах
|
|