/* @tier medium @module mg @transform msg-gateway-batch */ /* * mg_bt_0008.pgc - 채널 세션 만료 정리 배치 [tier=medium] * * 채널 세션(mg_chan) 중 마지막 활동시각(last_ts)이 유휴 임계(기본 * 900초)를 초과한 세션을 커서로 순회하며 raw SQL UPDATE 로 세션을 * 종료(sess_st='C') 처리한다. 정리 세션수/유지 세션수를 리포트한다. * * 실행: mg_bt_0008 [db@host] */ #include #include #include #include "txcore.h" #include "txcore_dbio.h" #include "acq_util.h" #include "mg_core.h" EXEC SQL INCLUDE sqlca; #define MG_SESS_IDLE_SEC 900 /* 세션 유휴 만료 임계(초) */ static int run_mg_bt_0008(const char *biz_date) { EXEC SQL BEGIN DECLARE SECTION; char h_chan_cd[8]; long h_sess_id; long h_idle; int h_idle_max; EXEC SQL END DECLARE SECTION; long total = 0, closed = 0, errcnt = 0; long longest = 0; h_idle_max = MG_SESS_IDLE_SEC; EXEC SQL DECLARE cur_mg_bt_0008 CURSOR FOR SELECT chan_cd, sess_id, CAST(EXTRACT(EPOCH FROM (now() - last_ts)) AS bigint) FROM mg_chan WHERE sess_st = 'A' AND EXTRACT(EPOCH FROM (now() - last_ts)) >= :h_idle_max ORDER BY chan_cd, sess_id; EXEC SQL OPEN cur_mg_bt_0008; if (sqlca.sqlcode != TX_SQL_OK) { TX_DBIO_LOG_ERR("OPEN cur_mg_bt_0008"); return TX_EDB; } if (tx_begin() != TX_OK) tx_log(TX_LOG_WARN, "[mg_bt_0008] tx_begin 경고"); for (;;) { EXEC SQL FETCH cur_mg_bt_0008 INTO :h_chan_cd, :h_sess_id, :h_idle; if (sqlca.sqlcode == TX_SQL_NOTFOUND) break; if (sqlca.sqlcode != TX_SQL_OK) { TX_DBIO_LOG_ERR("FETCH cur_mg_bt_0008"); errcnt++; break; } total++; if (h_idle > longest) longest = h_idle; EXEC SQL UPDATE mg_chan SET sess_st = 'C', close_ts = now() WHERE sess_id = :h_sess_id; if (sqlca.sqlcode != TX_SQL_OK) { TX_DBIO_LOG_ERR("UPDATE mg_chan close"); errcnt++; } else { closed++; tx_log(TX_LOG_DEBUG, "[mg_bt_0008] 세션종료 chan=%s sess=%ld idle=%lds", h_chan_cd, h_sess_id, h_idle); } } EXEC SQL CLOSE cur_mg_bt_0008; if (errcnt == 0) tx_commit(); else tx_abort(); tx_log(TX_LOG_INFO, "[mg_bt_0008] 세션정리 date=%s 종료=%ld 오류=%ld", biz_date, closed, errcnt); printf("========== 세션 만료 정리 [mg_bt_0008] ==========\n"); printf(" 기준일 : %s\n", biz_date); printf(" 유휴 임계(초) : %d\n", MG_SESS_IDLE_SEC); printf(" 만료 대상 : %ld\n", total); printf(" 종료 세션 : %ld\n", closed); printf(" 최장 유휴(초) : %ld\n", longest); printf(" 오류 건수 : %ld\n", errcnt); printf("=============================================\n"); return (errcnt == 0) ? TX_OK : TX_FAIL; } int main(int argc, char **argv) { const char *biz_date; const char *target; int rc; tx_set_loglevel(TX_LOG_INFO); if (argc < 2) { fprintf(stderr, "사용법: %s [db@host]\n", argv[0]); return 2; } biz_date = argv[1]; target = (argc >= 3) ? argv[2] : NULL; if (!date_is_valid(biz_date)) { fprintf(stderr, "오류: 유효하지 않은 영업일 '%s'\n", biz_date); return 2; } tx_log(TX_LOG_INFO, "[mg_bt_0008] 세션 만료 정리 시작 date=%s", biz_date); rc = mg_dbio_connect(target); if (rc != TX_OK) { tx_log(TX_LOG_ERROR, "[mg_bt_0008] DB 접속 실패 rc=%d", rc); return 1; } rc = run_mg_bt_0008(biz_date); mg_dbio_disconnect(); tx_log(TX_LOG_INFO, "[mg_bt_0008] 배치 종료 rc=%d(%s)", rc, tx_strerror(rc)); return (rc == TX_OK) ? 0 : 1; }