제13장 스케줄러 서비스 개발

내용 목차

13.1. 개요
13.1.1. 스케줄 아키텍처
13.1.2. 캘린더
13.2. 스케줄러 설정
13.3. 스케줄 관련 테이블
13.3.1. 스케줄 정보 테이블
13.3.2. 스케줄 상태 테이블
13.3.3. 스케줄 테이블 스크립트
13.3.4. 스케줄 테이블 데이터 예제
13.4. 스케줄 등록 및 관리를 위한 API

본 장에서는 스케줄러의 소개와 스케줄러 내부 구성 요소 및 개발에 대해 설명한다.

13.1. 개요

스케줄러는 사용자가 특정 시간대에 직접 실행하지 않고 스케줄 등록을 통해 특정 시간 특정 반복 등을 통해 런타임 운영 특히 주기적인 배치 실행에 도움을 주도록 하는 시스템이다.

스케줄러는 현재 스케줄 정보를 DB로 관리하며, 스케줄 정보를 ProManager를 통해 등록 및 수정하도록 되어 있다. 또한 영구적인 스케줄이 아닌 서버 기동할 때에만 존재해야 하는 스케줄의 경우 특정 API를 통해 DB에 등록할지(영구등록), 메모리상 등록할지 결정하여 업무에 맞게 스케줄 제어를 할 수 있다.

현재 스케줄 정보는 DB와 메모리에 존재하게 되며 DB에 존재하는 스케줄은 영구적인 스케줄을 등록할 때 사용되며, 메모리상 스케줄은 서버가 기동할 때에 API를 통해 등록하고 서버가 재부팅할 때에는 삭제된다.

스케줄러는 다음과 같은 기능들을 제공한다.

  • cron 표현식을 이용한 시간 작업 실행

    • 연, 월, 주, 일, 시, 분 등의 반복 및 시간 지정 가능하다.

    • cron 표현식은 Quartz의 cron format을 따른다.

    • http://www.cronmaker.com/을 통해 표현식을 간단히 생성 가능하다.

  • 스케줄 반복

    • 반복 횟수 지정 및 반복 주기 지정이 가능하다.

    • 반복 횟수를 무한으로 지정하여, 일반 배치를 스케줄하여 상주배치와 동일하게 활용 가능하다.

  • 스케줄 중복실행 여부 설정

    • 등록된 스케줄이 실행중일때에 다음 주기가 도달하여 실행할지, 실행을 방지할지 설정할 수 있다.

    • 업무상 해당 배치 혹은 서비스가 하나만 실행되어야 하는 경우 설정을 통해 스케줄 중복실행을 방지할 수 있다.

13.1.1. 스케줄 아키텍처

스케줄러는 ProObject 서버 내에 이벤트 및 시스템 서비스로 동작한다.

스케줄 설정이 된 경우에 기동할 때 ScheduleInitEvent 및 스케줄 서비스그룹이 기동되어 DB에서 스케줄을 읽어 스케줄을 구동한다.

스케줄러가 구동된 후 스케줄을 추가, 수정, 삭제하는 경우에는 ScheduleControlService를 통해 서버에 스케줄이 변경되었음을 알려 엔진에서 스케줄을 다시 읽어 동작하도록 한다.

[그림 13.1] 스케줄러 아키텍처

스케줄러 아키텍처

스케줄러의 서비스는 다음의 역할을 한다.

  • ScheduleControlService

    ScheduleControlService는 스케줄 실행 정보가 갱신되었음을 알려주며 추후에 필요한 경우 스케줄의 다른 명령들을 해당 서비스에서 처리할 예정이다. 해당 서비스는 시스템 서비스로 스케줄 서비스 그룹에 속해 있다. Input은 ScheduleControlDataObject를 사용하며, 설정해야 할 값은 없다.

13.1.2. 캘린더

캘린더는 스케줄 조건(cronExpression)으로 표현할 수 없는 휴일 및 영업일에 대한 처리를 위해 사용된다.

캘린더를 생성하여 Trigger 테이블의 biz_calId에 아이디를 입력하여 영업 캘린더로 사용할 수 있으며 Trigger 테이블의 holy_calId에 입력하여 휴일 캘린더로 활용할 수 있다. 캘린더는 baseCalendarId를 지정하여 다른 캘린더를 복합적으로 사용할 수 있다.

캘린더는 유형에 맞게 사용할 수 있도록 다양한 타입의 캘린더가 존재하며 캘린더를 조합하여 활용할 수 있다.

종류내용 및 예제

CRON

CronExpression으로 지정한다.

  • 데이터 및 형식 : Expression

  • 예제

    다음은 매일 15시 마다로 설정한 예이다.

    0 0 15 * * ?

ANNUAL

매 년 중 특정 월 일을 지정한다.

  • 데이터 및 형식 : MM.dd,MM.dd,MM.dd,....,

  • 예제

    다음은 매년 12월 25일 크리스마스, 매년 1월 1일을 설정한 예이다.

    01.01,12.25

MONTHLY

한달 중 특정 날짜를 지정한다.

  • 데이터 및 형식 : 1일,2일,3일….31일

  • 예제

    다음은 매달 3일은 정기휴일로 설정한 예이다.

    false,false,true,false,false,false,false,false,false,false
    ,false,false,false,false,false,false,false,false,false,false
    ,false,false,false,false,false,false,false,false,false,false,false

WEEKLY

요일 지정지정한다.

  • 데이터 및 형식 : 일,월,화,수,목...

  • 예제

    다음은 매주 토, 일을 휴무로 설정한 예이다.

    true,false,false,false,false,false,true 

DAILY

매일 하루 중 시간 지정한다.

  • 데이터 및 형식 : HH:mm,HH:mm

  • 예제

    다음은 오전 9시 ~오후 6시까지를 지정한 예이다.

    09:00,18:00 

RANGE

지정일자 ~ 지정일자 범위를 지정한다.

  • 데이터 및 형식 : yyyy.MM.dd HH:mm,yyyy.MM.dd HH:mm

  • 예제

    다음은 2018년 10월 10일 1시 0분~ 2018년 10월 10일 9시 0분을 설정한 예이다.

    2018.10.10 01:00,2018.10.10 09:00()

DAYS

날짜를 각각 지정한다.

  • 데이터 및 형식 : yyyy.MM.dd,yyyy.MM.dd,yyyy.MM.dd,yyyy.MM.dd

  • 예제

    다음은 2015년 8월 13일, 2015년 8월 15일, 2015년 8월 17일 휴가로 설정한 예이다.

    2015.08.13,2015.08.15,2015.08.17 

13.2. 스케줄러 설정

스케줄러를 사용하기 위해서는 테이블을 생성해야 하며, 서버 기동 이전에 다음의 파일에 설정한다.

${PROOBJECT_HOME}/config/proobject.xml

스케줄러가 스케줄 테이블에 접근하기 위해서는 데이터소스 설정이 필요하다. 해당 설정은 proobject.xml의 <engine-config> 하위에 <proObject-datasource>에 설정한다.

<proObject-datasource>에 이미 ${PROOBJECT_HOME}/system/config/dbio_config.xml에 설정한 alias 중에서 사용할 alias를 설정해야 한다.

<engine-config>
    <proObject-datasource>sc_ds</proObject-datasource>
</engine-config>

모든 스케줄 설정은 <schedule-config> 하위에 설정한다. <schedule-config>를 설정하게 되면 ProObject가 기동할 때 스케줄 서비스 그룹이 자동 등록되며, 스케줄 마스터 서비스(스케줄러)가 호출되어 스케줄이 동작한다.

다음은 스케줄 상태를 저장하도록 설정한 예이다.

<schedule-config>
    <schedule-status-enable>true</schedule-status-enable>
</schedule-config>
태그설명
<schedule-status-enable>

스케줄 상태를 기록할지 여부를 설정한다.

  • true : 스케줄 상태를 테이블에 기록한다.

  • false : 스케줄 상태를 테이블에 기록하지 않는다. (기본값)

13.3. 스케줄 관련 테이블

스케줄 관련 테이블은 등록된 스케줄 정보를 관리하는 테이블과 런타임에 스케줄 상태와 종료된 스케줄 상태를 관리하는 테이블로 구성된다.

  • 스케줄 정보 테이블

    테이블설명
    PO_Schedule_Main모든 정보의 키를 가지고 있으며 스케줄 아이디 및 유효 여부 등을 관리한다.
    PO_Schedule_Trigger스케줄이 실행될 조건의 대한 정보를 저장한다.
    PO_Schedule_TARGET조건에 부합한 경우 실행할 서비스 정보를 저장한다.
  • 스케줄 상태 테이블

    테이블설명
    PO_Schedule_Status실행 중인 스케줄 실행 정보를 저장한다
    PO_Schedule_History종료된 스케줄 정보를 저장하는 테이블이다.

13.3.1. 스케줄 정보 테이블

  • PO_Schedule_Main

    스케줄 메인 테이블로서 모든 정보의 키를 가지고 있으며 스케줄 아이디 및 유효 여부 등을 관리한다.

    컬럼설명
    sId스케줄 아이디를 저장한다.
    sName스케줄 이름을 저장한다. (논리명)
    userYn스케줄 사용 여부를 저장한다. (Y|N)
    startTime스케줄 사용가능 시작시간을 저장한다. 해당 시간 이전에는 스케줄이 동작하지 않는다.
    endTime스케줄 사용가능 종료시간을 저장한다. 해당 시간 이후에는 스케줄이 동작하지 않는다.
    sTrigerId스케줄 트리거 아이디를 저장한다. 트리거 테이블과 매핑되는 아이디이다.
    targetId스케줄 타켓 아이디를 저장한다. 타켓 테이블과 매핑되는 아이디이다.
    modifyTime스케줄 정보 수정 시간을 저장한다.
    invokeCnt

    스케줄의 호출 횟수를 설정한다.

    설정값이 0보다 크면 호출될때 마다 숫자를 하나씩 줄여나가며, 0이면 해당 스케줄은 더이상 동작하지 않는다. (기본값: -1, 무한)

    nodeId어떤 노드에서 해당 스케줄을 읽어 사용할지 지정한다. 수행시키고자 하는 proobject.xml의 <server-name>에 해당하는 값과 일치해야 한다.
  • PO_Schedule_Trigger

    스케줄이 실행될 조건의 대한 정보를 저장한다.

    컬럼설명
    sTrigerId스케줄 트리거 아이디를 저장한다.
    scheduleType

    스케줄 타입을 저장한다. 현재는 cron 타입으로만 동작한다.

    • cron : cronExpression에 따라 동작

    cronExpressioncronExpression를 저장한다. (예: "0 0/1 * 1/1 * ? *")
    biz_calId업무용 캘린더 아이디를 저장한다.
    holy_calId휴일용 캘린더 아이디를 저장한다.
    exceptionType

    cron 조건이 휴일일시를 처리할 타입을 저장한다.

    • W : 업무일 +1 -1 실행

    • WL : 가까운 업무일 실행, 동일 시 +1 -1에 따라 분기

    exceptionDatecron 조건이 휴일일시를 처리하는 방법을 저장한다.
    repeatMaxCnt해당 스케줄이 트리거되었을 때, 최대 반복 횟수를 저장한다.
    repeatInterval반복 주기를 저장한다. (단위: ms)
    dupleExeYn중복실행 가능 여부를 저장한다.
    invokeDelayTime조건 만족 후 호출 딜레이 정보를 저장한다.
  • PO_Schedule_TARGET

    조건에 부합한 경우 실행할 서비스 정보를 저장한다.

    컬럼설명
    targetId스케줄 타겟 아이디를 저장한다.
    exJobType

    실행 Job 종류를 저장한다.

    • JO

    • SO

    • SHELL

    exInputData
    • JO, SO : Input Json

    • SHELL : shell parameter

    exHeaderData
    • JO, SO : header Json

    • SHELL : null

    exNodeId스케줄이 실행되는 노드를 저장한다. PO_NODE 테이블의 NODE_ID 값이 입력된다.
    exName1
    • JO, SO : 애플리케이션 이름

    • SHELL : 셸 파일명

    exName2
    • JO, SO : 서버 그룹 이름

    • SHELL : 파일 경로

    exName3
    • JO, SO : 서비스 이름

    • SHELL : 사용하지 않음

13.3.2. 스케줄 상태 테이블

  • PO_Schedule_Status

    현재 실행 중인 스케줄 실행 정보를 저장하는 테이블이다.

    종료 이후에는 PO_Schedule_History로 데이터가 옮겨지게 된다. 또한 서버 이상으로 스케줄 실행 중 서버가 다운된 경우 부팅할 때 PO_Schedule_Status 정보를 PO_Schedule_History로 옮기게 된다.

    컬럼설명
    sId스케줄 ID를 저장한다.
    sExNum스케줄 실행번호를 저장한다.
    startTime스케줄 시작시간을 저장한다. (형식: YYYYMMddHHmmss)
    modifyTime최근 수정시간을 저장한다. (형식: YYYYMMddHHmmss)
    status

    상태를 저장한다.

    • PREPARE

    • RUNNING

    • TERMINATING

    repeatCnt현재 반복 회차를 저장한다.
    nodeId실행되고 있는 노드 아이디를 저장한다.
  • PO_Schedule_History

    종료된 스케줄 정보를 저장하는 테이블이다.

    컬럼설명
    sId스케줄 ID를 저장한다.
    sExNum스케줄 실행번호를 저장한다.
    status

    상태를 저장한다.

    • TERMINATED

    • COMPLETED

    • FAILED

    • REVISED

    startTime시작시간을 저장한다. (형식: YYYYMMddHHmmss)
    endTime종료시간을 저장한다. (형식: YYYYMMddHHmmss)
    errMsg에러 메시지를 저장한다.

13.3.3. 스케줄 테이블 스크립트

다음은 배치 생성 스크립트로 배치 내에 테스크 및 스탭, 파티셔너의 상태 및 종료 상태를 나타낸다.

-- PO_Schedule_Calendar Table Create SQL
CREATE TABLE PO_Schedule_Calendar
(
    calId            VARCHAR2(64)    NOT NULL, 
    calName          VARCHAR2(64)    NULL, 
    calendarType     VARCHAR2(20)    NULL, 
    pattern          VARCHAR2(4000)    NULL, 
    parentCalId        VARCHAR2(64)    NULL,
    exclusiveFlag      VARCHAR2(5)    NULL,
--    exceptionType    VARCHAR2(20)    NULL, 
--    exceptionDate    VARCHAR2(20)    NULL, 
    CONSTRAINT PO_Schedule_Calendar_PK PRIMARY KEY (calId)
)
/

COMMENT ON TABLE PO_Schedule_Calendar IS '스케줄 캘린더'
/

COMMENT ON COLUMN PO_Schedule_Calendar.calId IS '캘린더 ID'
/

COMMENT ON COLUMN PO_Schedule_Calendar.calName IS '캘린더 명'
/

COMMENT ON COLUMN PO_Schedule_Calendar.calendarType IS '캘린더타입(일,주,월,ad)'
/

COMMENT ON COLUMN PO_Schedule_Calendar.pattern IS '캘린더 패턴'


--  Table Create SQL
CREATE TABLE PO_Schedule_Trigger
(
    sTrigerId          VARCHAR2(64)      NOT NULL, 
    scheduleType       VARCHAR2(20)      NULL, 
    cronExpression     VARCHAR2(30)      NULL, 
    biz_calId          VARCHAR2(64)      NULL,
    holy_calId         VARCHAR2(64)      NULL,
    exceptionType      VARCHAR2(20)      NULL, 
    exceptionDate      VARCHAR2(20)      NULL,
    repeatMaxCnt       NUMBER(18, 0)     NULL, 
    repeatInterval     NUMBER(18, 0)     NULL, 
    dupleExeYn         VARCHAR2(1)       NULL, 
    invokeDelayTime    NUMBER(18, 0)     NULL, 
    CONSTRAINT PO_Schedule_Trigger_PK PRIMARY KEY (sTrigerId)
)
/

COMMENT ON TABLE PO_Schedule_Trigger IS '스케줄 실행 조건'
/

COMMENT ON COLUMN PO_Schedule_Trigger.sTrigerId IS '스케줄 트리거 ID'
/

COMMENT ON COLUMN PO_Schedule_Trigger.scheduleType IS 'cron(캘린더 만들지 않고), calendar'
/

COMMENT ON COLUMN PO_Schedule_Trigger.cronExpression IS 'scheduleType가 cron일 경우 Expression'
/

COMMENT ON COLUMN PO_Schedule_Trigger.repeatMaxCnt IS '최대 반복 횟수'
/

COMMENT ON COLUMN PO_Schedule_Trigger.repeatInterval IS '반복 주기(ms)'
/

COMMENT ON COLUMN PO_Schedule_Trigger.dupleExeYn IS '중복실행가능여부'
/

COMMENT ON COLUMN PO_Schedule_Trigger.invokeDelayTime IS 'invoke 조건 만족 후, 호출 딜레이'
/



-- PO_Schedule_Main Table Create SQL
CREATE TABLE PO_Schedule_Main
(
    sId           VARCHAR2(64)    NOT NULL, 
    sName         VARCHAR2(64)    NULL, 
    userYn        VARCHAR2(1)     NULL, 
    startTime     VARCHAR2(14)    NULL, 
    endTime       VARCHAR2(14)    NULL, 
    sTrigerId     VARCHAR2(64)    NULL, 
    targetId      VARCHAR2(64)    NULL, 
    modifyTime    VARCHAR2(14)    NULL,
    invokeCnt     NUMBER(5, 0)    default -1,
    nodeId        VARCHAR2(128)   NULL,
    CONSTRAINT PO_Schedule_Main_PK PRIMARY KEY (sId)
)
/

COMMENT ON TABLE PO_Schedule_Main IS '스케줄 메인'
/

COMMENT ON COLUMN PO_Schedule_Main.sId IS '스케줄 ID'
/

COMMENT ON COLUMN PO_Schedule_Main.sName IS '스케줄명'
/

COMMENT ON COLUMN PO_Schedule_Main.userYn IS '스케줄 사용여부'
/

COMMENT ON COLUMN PO_Schedule_Main.startTime IS '스케줄 실행 가능시간(YYYYMMddHHmmss)'
/

COMMENT ON COLUMN PO_Schedule_Main.endTime IS '스케줄 유효 만료 시간(YYYYMMddHHmmss)'
/

COMMENT ON COLUMN PO_Schedule_Main.sTrigerId IS '스케줄 트리거 ID'
/

COMMENT ON COLUMN PO_Schedule_Main.targetId IS '실행 Job ID'
/

COMMENT ON COLUMN PO_Schedule_Main.modifyTime IS '최근 수정시간(YYYYMMddHHmmss)'
/



-- PO_Schedule_Main Table Create SQL
CREATE TABLE PO_Schedule_Status
(
    sId               VARCHAR2(64)     NOT NULL, 
    sExNum            VARCHAR2(64)     NULL,
    startTime         VARCHAR2(14)     NULL,
    modifyTime        VARCHAR2(14)     NULL, 
    status            VARCHAR2(20)     NULL, 
    repeatCnt         NUMBER(18, 0)    NULL, 
    nodeId            VARCHAR2(128)    NULL, 
    CONSTRAINT PO_Schedule_Status_PK PRIMARY KEY (sId, sExNum)
)
/

COMMENT ON TABLE PO_Schedule_Status IS '스캐쥴 진행중에만 해당 테이블 사용하며 종료시 PO_Schedule_History 로 데이터 전달'
/

COMMENT ON COLUMN PO_Schedule_Status.sId IS '스케줄 ID'
/

COMMENT ON COLUMN PO_Schedule_Status.sExNum IS '스케줄 실행번호'
/

COMMENT ON COLUMN PO_Schedule_Status.modifyTime IS '최근 수정시간(YYYYMMddHHmmss)'
/

COMMENT ON COLUMN PO_Schedule_Status.status IS '상태(PREPARE, RUNNING, TERMINATING)'
/

COMMENT ON COLUMN PO_Schedule_Status.repeatCnt IS '현재 반복 회차'
/

COMMENT ON COLUMN PO_Schedule_Status.nodeId IS '실행되고 있는 노드 아이디'
/

-- PO_Schedule_History Table Create SQL
CREATE TABLE PO_Schedule_History
(
    sId          VARCHAR2(64)    NOT NULL, 
    sExNum       VARCHAR2(64)    NULL, 
    status       VARCHAR2(20)    NULL, 
    startTime    VARCHAR2(14)    NULL, 
    endTime      VARCHAR2(14)    NULL,
    nodeId       VARCHAR2(128)   NULL,
    errMsg       VARCHAR2(4000)  NULL,
    CONSTRAINT PO_Schedule_History_PK PRIMARY KEY (sId,sExNum)
)
/

COMMENT ON TABLE PO_Schedule_History IS '스케줄 히스토리'
/

COMMENT ON COLUMN PO_Schedule_History.sId IS '스케줄 ID'
/

COMMENT ON COLUMN PO_Schedule_History.sExNum IS '스케줄 실행번호'
/

COMMENT ON COLUMN PO_Schedule_History.status IS '상태(TERMINATED,  COMPLETED, FAILED, REVISED)'
/

COMMENT ON COLUMN PO_Schedule_History.startTime IS '시작시간(YYYYMMddHHmmss)'
/

COMMENT ON COLUMN PO_Schedule_History.endTime IS '종료시간(YYYYMMddHHmmss)'
/

-- PO_Schedule_TARGET Table Create SQL
CREATE TABLE PO_Schedule_TARGET
(
    targetId       VARCHAR2(64)    NOT NULL, 
    exJobType      VARCHAR2(20)    NULL, 
    exInputData    VARCHAR2(4000)  NULL,
    exHeaderData   VARCHAR2(4000)  NULL,
    exNodeId       VARCHAR2(128)   NULL, 
    exName1        VARCHAR2(64)    NULL, 
    exName2        VARCHAR2(64)    NULL, 
    exName3        VARCHAR2(64)    NULL, 
    CONSTRAINT PO_Schedule_TARGET_PK PRIMARY KEY (targetI d)
)
/

COMMENT ON TABLE PO_Schedule_TARGET IS '스케줄 실행 대상 정보'
/

COMMENT ON COLUMN PO_Schedule_TARGET.targetId IS '실행 Job ID'
/

COMMENT ON COLUMN PO_Schedule_TARGET.exJobType IS '실행 Job 종류(JO,SO,shell)'
/

COMMENT ON COLUMN PO_Schedule_TARGET.exInputData IS 'JO, SO : InputMsgText, Shell : shell parameter'
/

COMMENT ON COLUMN PO_Schedule_TARGET.exNodeId IS '스케줄이 실행되는 노드'
/

COMMENT ON COLUMN PO_Schedule_TARGET.exName1 IS 'JO, SO : ApplicationName, Shell : shell파일명'
/

COMMENT ON COLUMN PO_Schedule_TARGET.exName2 IS 'JO, SO : ServiceGroup, Shell : 파일 경로'
/

COMMENT ON COLUMN PO_Schedule_TARGET.exName3 IS 'JO, SO : Service, Shell : 사용하지 않음'
/

13.3.4. 스케줄 테이블 데이터 예제

ProObject는 ProManager를 통해 스케줄을 관리한다.

다음은 ProManager 없이 사용해야 하는 경우를 위한 스케줄 테이블에 대한 데이터 예제이다.

--5초 마다 스케줄, 반복 없음, 중복실행 없음
INSERT INTO PO_Schedule_Main (sId, sName, userYn, startTime, endTime, sTrigerId, targetId, modifyTime, nodeid) 
VALUES ('sId1', 'sName1', 'y', '20170101010101', '20200101010101', 'sId1_TR', 'sId1_TA', '20170101010101', 'ProObject7');

INSERT INTO PO_Schedule_Trigger (sTrigerId, scheduleType, cronExpression, repeatMaxCnt, repeatInterval, dupleExeYn, invokeDelayTime) 
VALUES ('sId1_TR', 'cron', '0/5 * * * * ?', 0,0, 'n', 1);

INSERT INTO PO_Schedule_TARGET (targetId, exJobType, exInputData, exNodeId, exName1, exName2, exName3) 
VALUES ('sId1_TA', 'SO', '', '', 'test', 'example', 'JobServiceCCTargetSample');

--1분 마다 스케줄, 반복 없음, 중복실행 없음
INSERT INTO PO_Schedule_Main (sId, sName, userYn, startTime, endTime, sTrigerId, targetId, modifyTime, nodeid) 
VALUES ('sId2', 'sName2', 'y', '20170101010101', '20200101010101', 'sId2_TR', 'sId2_TA', '20170101010101', 'ProObject7');

INSERT INTO PO_Schedule_Trigger (sTrigerId, scheduleType, cronExpression, repeatMaxCnt, repeatInterval, dupleExeYn, invokeDelayTime) 
VALUES ('sId2_TR', 'cron', '0 0/1 * 1/1 * ? *', 0,0, 'n', 1);

INSERT INTO PO_Schedule_TARGET (targetId, exJobType, exInputData, exNodeId, exName1, exName2, exName3) 
VALUES ('sId2_TA', 'SO', '', '', 'test', 'example', 'JobServiceCCTargetSample');

--1분 마다 스케줄, 무한반복 2초간격, 중복실행 없음
INSERT INTO PO_Schedule_Main (sId, sName, userYn, startTime, endTime, sTrigerId, targetId, modifyTime, nodeid) 
VALUES ('sId3', 'sName3', 'y', '20170101010101', '20200101010101', 'sId3_TR', 'sId3_TA', '20170101010101', 'ProObject7');

INSERT INTO PO_Schedule_Trigger (sTrigerId, scheduleType, cronExpression, repeatMaxCnt, repeatInterval, dupleExeYn, invokeDelayTime) 
VALUES ('sId3_TR', 'cron', '0 0/1 * 1/1 * ? *',-1,2000, 'n', 1);

INSERT INTO PO_Schedule_TARGET (targetId, exJobType, exInputData, exNodeId, exName1, exName2, exName3) 
VALUES ('sId3_TA', 'SO', '', '', 'test', 'example', 'JobServiceCCTargetSample');


--4초 마다 스케줄, 반복 없음, 중복실행 없음, input값 있음
INSERT INTO PO_Schedule_Main (sId, sName, userYn, startTime, endTime, sTrigerId, targetId, modifyTime, nodeid) 
VALUES ('sId4', 'sName4', 'y', '20170101010101', '20200101010101', 'sId4_TR', 'sId4_TA', '20170101010101', 'ProObject7');

INSERT INTO PO_Schedule_Trigger (sTrigerId, scheduleType, cronExpression, repeatMaxCnt, repeatInterval, dupleExeYn, invokeDelayTime) 
VALUES ('sId4_TR', 'cron', '0/4 * * * * ?',0,0, 'n', 1);

INSERT INTO PO_Schedule_TARGET (targetId, exJobType, exInputData, exNodeId, exName1, exName2, exName3) 
VALUES ('sId4_TA', 'SO', '{"cc_id":"SAMPLE1","cc_exe_id":"testEx1","retry_yn":"n"}', '', 'test', 'example', 'JobServiceCCTargetSample');

--5초 마다 스케줄, 반복 없음, 중복실행 없음, 배치 실행
INSERT INTO PO_Schedule_Main (sId, sName, userYn, startTime, endTime, sTrigerId, targetId, modifyTime, nodeid) 
VALUES ('sId5', 'sName5', 'y', '20170101010101', '20200101010101', 'sId5_TR', 'sId5_TA', '20170101010101', 'ProObject7');

INSERT INTO PO_Schedule_Trigger (sTrigerId, scheduleType, cronExpression, repeatMaxCnt, repeatInterval, dupleExeYn, invokeDelayTime) 
VALUES ('sId5_TR', 'cron', '0/5 * * * * ?',0,0, 'n', 1);

INSERT INTO PO_Schedule_TARGET (targetId, exJobType, exInputData, exNodeId, exName1, exName2, exName3) 
VALUES ('sId5_TA', 'JO', '', '', 'test', 'svcGrpTest', 'JobServiceNormalSample');


--5초 마다 스케줄, 반복 없음, 중복실행 없음, 프로배치 실행
INSERT INTO PO_Schedule_Main (sId, sName, userYn, startTime, endTime, sTrigerId, targetId, modifyTime, nodeId) 
VALUES ('sId10', 'sName10', 'y', '20170101010101', '20200101010101', 'sId10_TR', 'sId10_TA', '20170101010101', 'ProObject7');

INSERT INTO PO_Schedule_Trigger (sTrigerId, scheduleType, cronExpression, repeatMaxCnt, repeatInterval, dupleExeYn, invokeDelayTime) 
VALUES ('sId10_TR', 'cron', '0/5 * * * * ?',0,0, 'n', 1);

INSERT INTO PO_Schedule_TARGET (targetId, exJobType, exInputData, exNodeId, exName1, exName2, exName3) 
VALUES ('sId10_TA', 'PROBATCH', '', 'ProBatch_1', '', '', 'JobServiceNormalSample');



truncate table PO_Schedule_Main;
truncate table PO_Schedule_TARGET;
truncate table PO_Schedule_Trigger;

--INSERT INTO PO_Schedule_Calendar (calId, calName, calendarType, pattern, inCalId, exCalId, exceptionType, exceptionDate) 
VALUES ('calId1', '', '', '', '', '', '', '');
--INSERT INTO PO_Schedule_Calendar (calId, calName, calendarType, pattern, inCalId, exCalId, exceptionType, exceptionDate) 
VALUES ('calId2', '', '', '', '', '', '', '');
--truncate table PO_Schedule_Calendar;


--정상 등록되었는지 확인하는 쿼리
SELECT * 
FROM PO_Schedule_Main main, PO_Schedule_Trigger tri, PO_Schedule_TARGET tar
WHERE main.sTrigerId=tri.sTrigerId AND main.targetId=tar.targetId;



---calenar data
insert into PO_Schedule_Calendar (calId, calName, calendarType, pattern, parentCalId, exclusiveFlag) 
values ('cron_daily', 'cron_daily', 'CRON', '15 0 * * * ?', '', 'false');

insert into PO_Schedule_Calendar(calId, calName, calendarType, pattern, parentCalId, exclusiveFlag) 
values ('anual_daily', 'anual_daily', 'ANNUAL', '11.28,11.30,12.01,12.03,12.05', '', 'false');

insert into PO_Schedule_Calendar (calId, calName, calendarType, pattern, parentCalId, exclusiveFlag) 
values ('month_daily', 'month_daily', 'MONTHLY', 
'true,false,false,false,false,false,false,false,false,false,false,false,false,false,
false,false,false,false,false,false,false,false,false,false,false,false,false,false,
false,false,false', '', 'false');



insert into PO_Schedule_Calendar (calId, calName, calendarType, pattern, parentCalId, exclusiveFlag) 
values('calId_weekly', 'calId_weekly', 'WEEKLY', 'false,false,false,false,false,false,false', '', 'false');

insert into PO_Schedule_Calendar (calId, calName, calendarType, pattern, parentCalId, exclusiveFlag) 
values ('calId_daily', 'calId_daily', 'DAILY', '09:00,18:00', '', 'false');

insert into PO_Schedule_Calendar (calId, calName, calendarType, pattern, parentCalId, exclusiveFlag) 
values ('calId_RANGE', 'calId_RANGE', 'RANGE', '2018.11.28 09:00,2018.12.02 19:00', '', 'false');

insert into PO_Schedule_Calendar (calId, calName, calendarType, pattern, parentCalId, exclusiveFlag) 
values ('calId_DAYS', 'calId_DAYS', 'DAYS', '2018.11.28,2018.12.02,2018.12.03', '', 'false');


--
--5초 마다 스케줄, 반복 없음, 중복실행 없음
INSERT INTO PO_Schedule_Main (sId, sName, userYn, startTime, endTime, sTrigerId, targetId, modifyTime) 
VALUES ('exT1', 'sName1', 'y', '20170101010101', '20200101010101', 'exT1_TR', 'exT1_TA', '20170101010101');

INSERT INTO PO_Schedule_Trigger(sTrigerId, scheduleType, cronExpression, repeatMaxCnt, repeatInterval, 
dupleExeYn, invokeDelayTime, biz_calId, holy_calId) 
VALUES ('exT1_TR', 'cron', '0/5 * * * * ?', 0,0, 'n', 1, 'ExCanual_daily', '');

INSERT INTO PO_Schedule_TARGET (targetId, exJobType, exInputData, exNodeId, exName1, exName2, exName3) 
VALUES ('exT1_TA', 'SO', '', '', 'proobject', 'batch', 'JobServiceCCTargetSample');

 
insert into PO_Schedule_Calendar (calId, calName, calendarType, pattern, parentCalId, exclusiveFlag) 
values ( 'ExCanual_daily', 'ExCanual_daily', 'ANNUAL', '', '', 'false'); 

13.4. 스케줄 등록 및 관리를 위한 API

기존 스케줄 데이터는 DB를 통해 관리되었기 때문에 DB에 데이터를 삭제하거나 수정하지 않는 한 영구적으로 지속되었다. 하지만 원하는 시점에 등록된 후 서버가 다운되었을 때 스케줄이 더이상 유효하지 않아야 하는 경우 메모리상에만 존재하도록 할 필요 있다.

이러한 경우 다음의 API를 사용할 수 있으며, DB 스케줄에 대해서도 등록이 가능하다.

////////////스케줄 데이터 생성 시작////////////
ServiceName name = new ServiceName("appName", "svcgrpName", "JobServiceNormalSample");
ScheduleBuilder builder = new ScheduleBuilder();

//appName, svcGrpName, svcName, inputJson
builder.configJob(name.getApplicationName(), name.getServiceGroupName(), name.getServiceName(), 
"{\"cc_id\":\"SAMPLE1\",\"cc_exe_id\":\"testEx1\",\"retry_yn\":\"n\"}");

builder.configCron("0/5 * * * * ?");//5초마다
//builder.configValidTime("20110101235000", "20200101235000");
//builder.configRepeat(-1, 1000, false);
ScheduleModelSet set = builder.build("scheduleId1", "ScheduleName1");
////////////스케줄 데이터 생성 끝////////////


//스케줄을 등록하며, 등록한 시점부터 동작한다.
ScheduleRegister.getInstance().regist(set, Storage_Type.MEMORY);//메모리에 스케줄을 등록한다.
//ScheduleRegister.getInstance().regist(set, Storage_Type.DB);//DB에 스케줄을 등록한다.

//스케줄을 삭제한다.
ScheduleRegister.getInstance().unregist("scheduleId1");//메모리에 sid가 있으면 삭제하며, 메모리에 없으면 DB에 delete를 수행한다.
//ScheduleRegister.getInstance().unregist("scheduleId1", Storage_Type.MEMORY);//메모리에 등록된 sid를 삭제한다.
//ScheduleRegister.getInstance().unregist("scheduleId1", Storage_Type.DB);//DB에 등록된 sid를 삭제한다.
String sId = "scheduleId1";
String sName = "ScheduleName1";

ScheduleModelSet set = new ScheduleModelSet();
ScheduleBuilder builder = new ScheduleBuilder();
builder.configCron("0/30 * * 1/1 * ? 2019");
builder.configJob("test", "main","S_Callee","");
builder.configValidTime("20190819110000", "99990819111500");

set=builder.build(sId, sName);
set.getMainModel().setSid("scheduleId1");
set.getMainModel().setDisposableYn(true);
set.getMainModel().setExjobid(null);
set.getMainModel().setInvokeCnt(0);
set.getMainModel().setModifytime("20190823174150");
set.getMainModel().setNodeId("scheduleId1_TA");
set.getMainModel().setSname(sName);
set.getMainModel().setStarttime("30000819110000");
set.getMainModel().setStrigerid("scheduleId1_TR");
set.getMainModel().setUseryn("Y");
set.getTriggerModel().setCronexpression("0/30 * * 1/1 * ? 2019");

ScheduleRegister.getInstance().modify(set, Storage_Type.DB);

ScheduleControlDataObject _scheduleControlDataObject = new ScheduleControlDataObject();
try {
    RequestContext requestContext = ServiceManager.getServiceRequestContext("proobject.schedule.ScheduleControlService");
    ServiceManager.call(requestContext, "proobject.schedule.ScheduleControlService", _scheduleControlDataObject);
   } catch (ServiceCallFailedException e){
}