initial commit
This commit is contained in:
297
Scripts/DC_BACKEND_PKG.sql
Normal file
297
Scripts/DC_BACKEND_PKG.sql
Normal file
@@ -0,0 +1,297 @@
|
||||
-- =============================================================================
|
||||
-- DC_BACKEND_PKG
|
||||
-- PL/SQL-Schnittstelle zum Quarkus dc-backend (Kubernetes Service dc-backend:8090)
|
||||
--
|
||||
-- Voraussetzungen:
|
||||
-- - APEX_WEB_SERVICE-Berechtigung für das Schema:
|
||||
-- GRANT EXECUTE ON APEX_240100.APEX_WEB_SERVICE TO <schema>; -- APEX-Version anpassen
|
||||
-- - ACL für ausgehende HTTP-Verbindung im selben Namespace:
|
||||
-- DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
|
||||
-- host => 'dc-backend', lower_port => 8090, upper_port => 8090,
|
||||
-- ace => xs$ace_type(privilege_list => xs$name_list('connect','resolve'),
|
||||
-- principal_name => '<schema>', principal_type => xs_acl.ptype_db));
|
||||
--
|
||||
-- Deployment:
|
||||
-- sqlplus user/pass@db @"Scripts/DC_BACKEND_PKG.sql"
|
||||
-- =============================================================================
|
||||
|
||||
|
||||
-- =============================================================================
|
||||
-- Package Spec
|
||||
-- =============================================================================
|
||||
CREATE OR REPLACE PACKAGE DC_BACKEND_PKG AS
|
||||
|
||||
-- Basis-URL des dc-backend Kubernetes Service
|
||||
c_base_url CONSTANT VARCHAR2(200) := 'http://dc-backend:8090';
|
||||
|
||||
-- API-Key (X-API-KEY Header).
|
||||
-- Leer = kein Auth (Dev-Modus).
|
||||
-- Zur Laufzeit setzen: DC_BACKEND_PKG.g_api_key := 'mein-key';
|
||||
g_api_key VARCHAR2(500) := '';
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
-- Startet die KI-gestützte Dokumentenprüfung für ein Projekt (asynchron).
|
||||
-- Das Projekt muss im Status PENDING sein.
|
||||
-- POST /check/{p_project_id} → 202 Accepted
|
||||
--
|
||||
-- p_project_id ID des dc_projects-Eintrags
|
||||
-- p_status_code HTTP-Statuscode der Antwort (202 = OK, 409 = nicht PENDING)
|
||||
-- p_response JSON-Antwort des Backend
|
||||
-- -------------------------------------------------------------------------
|
||||
PROCEDURE start_check(
|
||||
p_project_id IN NUMBER,
|
||||
p_status_code OUT NUMBER,
|
||||
p_response OUT VARCHAR2
|
||||
);
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
-- Health-Check: prüft ob der dc-backend Service erreichbar ist.
|
||||
-- GET /check/health → 200 UP
|
||||
--
|
||||
-- Rückgabe: TRUE = Service läuft, FALSE = nicht erreichbar
|
||||
-- -------------------------------------------------------------------------
|
||||
FUNCTION health_check RETURN BOOLEAN;
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
-- Startet die Prüfung und wirft eine Exception wenn nicht 202 zurückkommt.
|
||||
-- Convenience-Wrapper für direkte APEX-Button-Aufrufe.
|
||||
-- -------------------------------------------------------------------------
|
||||
PROCEDURE start_check_or_raise(
|
||||
p_project_id IN NUMBER
|
||||
);
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
-- Fortschritts-Record
|
||||
-- -------------------------------------------------------------------------
|
||||
TYPE t_project_status IS RECORD (
|
||||
status dc_projects.status%TYPE,
|
||||
processing_progress dc_projects.progress%TYPE,
|
||||
is_completed BOOLEAN,
|
||||
is_running BOOLEAN,
|
||||
is_pending BOOLEAN
|
||||
);
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
-- Liest Status und Fortschritt eines Projekts direkt aus der DB.
|
||||
-- Kein REST-Aufruf – sofort und transaktionssicher.
|
||||
--
|
||||
-- Beispiel:
|
||||
-- l_s := DC_BACKEND_PKG.get_status(1);
|
||||
-- DBMS_OUTPUT.PUT_LINE(l_s.status || ' ' || l_s.processing_progress || '%');
|
||||
-- -------------------------------------------------------------------------
|
||||
FUNCTION get_status(
|
||||
p_project_id IN NUMBER
|
||||
) RETURN t_project_status;
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
-- Wartet (polling) bis das Projekt COMPLETED oder ein Timeout erreicht ist.
|
||||
-- Wirft eine Exception bei Timeout oder wenn das Projekt nicht gefunden wird.
|
||||
--
|
||||
-- p_timeout_sec Max. Wartezeit in Sekunden (Default: 1800 = 30 Min.)
|
||||
-- p_interval_sec Polling-Intervall in Sekunden (Default: 5)
|
||||
-- -------------------------------------------------------------------------
|
||||
PROCEDURE wait_for_completion(
|
||||
p_project_id IN NUMBER,
|
||||
p_timeout_sec IN NUMBER DEFAULT 1800,
|
||||
p_interval_sec IN NUMBER DEFAULT 5
|
||||
);
|
||||
|
||||
END DC_BACKEND_PKG;
|
||||
/
|
||||
|
||||
|
||||
-- =============================================================================
|
||||
-- Package Body
|
||||
-- =============================================================================
|
||||
CREATE OR REPLACE PACKAGE BODY DC_BACKEND_PKG AS
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
-- Setzt gemeinsame Request-Header (Content-Type + optional API-Key)
|
||||
-- -------------------------------------------------------------------------
|
||||
PROCEDURE set_headers IS
|
||||
l_idx PLS_INTEGER := 1;
|
||||
BEGIN
|
||||
APEX_WEB_SERVICE.G_REQUEST_HEADERS.DELETE;
|
||||
|
||||
APEX_WEB_SERVICE.G_REQUEST_HEADERS(l_idx).NAME := 'Content-Type';
|
||||
APEX_WEB_SERVICE.G_REQUEST_HEADERS(l_idx).VALUE := 'application/json';
|
||||
l_idx := l_idx + 1;
|
||||
|
||||
IF g_api_key IS NOT NULL AND LENGTH(TRIM(g_api_key)) > 0 THEN
|
||||
APEX_WEB_SERVICE.G_REQUEST_HEADERS(l_idx).NAME := 'X-API-KEY';
|
||||
APEX_WEB_SERVICE.G_REQUEST_HEADERS(l_idx).VALUE := g_api_key;
|
||||
END IF;
|
||||
END set_headers;
|
||||
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
PROCEDURE start_check(
|
||||
p_project_id IN NUMBER,
|
||||
p_status_code OUT NUMBER,
|
||||
p_response OUT VARCHAR2
|
||||
) IS
|
||||
l_url VARCHAR2(500);
|
||||
l_response CLOB;
|
||||
BEGIN
|
||||
l_url := c_base_url || '/check/' || TO_CHAR(p_project_id);
|
||||
|
||||
set_headers();
|
||||
|
||||
l_response := APEX_WEB_SERVICE.MAKE_REST_REQUEST(
|
||||
p_url => l_url,
|
||||
p_http_method => 'POST',
|
||||
p_body => '{}' -- leerer Body, projectId ist im Pfad
|
||||
);
|
||||
|
||||
p_status_code := APEX_WEB_SERVICE.G_STATUS_CODE;
|
||||
p_response := SUBSTR(l_response, 1, 4000);
|
||||
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
p_status_code := -1;
|
||||
p_response := 'Verbindungsfehler: ' || SQLERRM;
|
||||
END start_check;
|
||||
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
FUNCTION health_check RETURN BOOLEAN IS
|
||||
l_url VARCHAR2(500);
|
||||
l_response CLOB;
|
||||
l_status NUMBER;
|
||||
BEGIN
|
||||
l_url := c_base_url || '/check/health';
|
||||
|
||||
set_headers();
|
||||
|
||||
l_response := APEX_WEB_SERVICE.MAKE_REST_REQUEST(
|
||||
p_url => l_url,
|
||||
p_http_method => 'GET'
|
||||
);
|
||||
|
||||
l_status := APEX_WEB_SERVICE.G_STATUS_CODE;
|
||||
RETURN l_status = 200;
|
||||
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
RETURN FALSE;
|
||||
END health_check;
|
||||
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
PROCEDURE start_check_or_raise(
|
||||
p_project_id IN NUMBER
|
||||
) IS
|
||||
l_status NUMBER;
|
||||
l_response VARCHAR2(4000);
|
||||
BEGIN
|
||||
start_check(
|
||||
p_project_id => p_project_id,
|
||||
p_status_code => l_status,
|
||||
p_response => l_response
|
||||
);
|
||||
|
||||
IF l_status = 202 THEN
|
||||
-- OK: Verarbeitung wurde gestartet
|
||||
NULL;
|
||||
ELSIF l_status = 409 THEN
|
||||
RAISE_APPLICATION_ERROR(-20100,
|
||||
'Projekt ' || p_project_id || ' ist nicht im Status PENDING.');
|
||||
ELSIF l_status = 401 THEN
|
||||
RAISE_APPLICATION_ERROR(-20101,
|
||||
'Ungültiger API-Key für dc-backend.');
|
||||
ELSIF l_status = -1 THEN
|
||||
RAISE_APPLICATION_ERROR(-20102,
|
||||
'dc-backend nicht erreichbar: ' || l_response);
|
||||
ELSE
|
||||
RAISE_APPLICATION_ERROR(-20103,
|
||||
'Unerwarteter HTTP-Status ' || l_status || ': ' || l_response);
|
||||
END IF;
|
||||
END start_check_or_raise;
|
||||
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
FUNCTION get_status(
|
||||
p_project_id IN NUMBER
|
||||
) RETURN t_project_status IS
|
||||
l_rec t_project_status;
|
||||
BEGIN
|
||||
SELECT status, progress
|
||||
INTO l_rec.status, l_rec.processing_progress
|
||||
FROM dc_projects
|
||||
WHERE id = p_project_id;
|
||||
|
||||
l_rec.is_completed := l_rec.status = 'COMPLETED';
|
||||
l_rec.is_running := l_rec.status = 'IN_PROGRESS';
|
||||
l_rec.is_pending := l_rec.status = 'PENDING';
|
||||
RETURN l_rec;
|
||||
|
||||
EXCEPTION
|
||||
WHEN NO_DATA_FOUND THEN
|
||||
RAISE_APPLICATION_ERROR(-20110,
|
||||
'Projekt ' || p_project_id || ' nicht gefunden.');
|
||||
END get_status;
|
||||
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
PROCEDURE wait_for_completion(
|
||||
p_project_id IN NUMBER,
|
||||
p_timeout_sec IN NUMBER DEFAULT 1800,
|
||||
p_interval_sec IN NUMBER DEFAULT 5
|
||||
) IS
|
||||
l_start TIMESTAMP := SYSTIMESTAMP;
|
||||
l_status t_project_status;
|
||||
BEGIN
|
||||
LOOP
|
||||
l_status := get_status(p_project_id);
|
||||
|
||||
EXIT WHEN l_status.is_completed;
|
||||
|
||||
IF EXTRACT(SECOND FROM (SYSTIMESTAMP - l_start))
|
||||
+ EXTRACT(MINUTE FROM (SYSTIMESTAMP - l_start)) * 60
|
||||
+ EXTRACT(HOUR FROM (SYSTIMESTAMP - l_start)) * 3600
|
||||
> p_timeout_sec
|
||||
THEN
|
||||
RAISE_APPLICATION_ERROR(-20111,
|
||||
'Timeout nach ' || p_timeout_sec || 's – Projekt ' ||
|
||||
p_project_id || ' noch im Status ' || l_status.status ||
|
||||
' (' || l_status.processing_progress || '%).');
|
||||
END IF;
|
||||
|
||||
DBMS_SESSION.SLEEP(p_interval_sec);
|
||||
END LOOP;
|
||||
END wait_for_completion;
|
||||
|
||||
|
||||
END DC_BACKEND_PKG;
|
||||
/
|
||||
|
||||
|
||||
-- =============================================================================
|
||||
-- Schnelltest (optional, auskommentiert)
|
||||
-- =============================================================================
|
||||
/*
|
||||
-- Health-Check
|
||||
BEGIN
|
||||
IF DC_BACKEND_PKG.health_check() THEN
|
||||
DBMS_OUTPUT.PUT_LINE('dc-backend: UP');
|
||||
ELSE
|
||||
DBMS_OUTPUT.PUT_LINE('dc-backend: NICHT ERREICHBAR');
|
||||
END IF;
|
||||
END;
|
||||
/
|
||||
|
||||
-- Prüfung starten (Projekt-ID anpassen)
|
||||
DECLARE
|
||||
l_status NUMBER;
|
||||
l_response VARCHAR2(4000);
|
||||
BEGIN
|
||||
DC_BACKEND_PKG.start_check(
|
||||
p_project_id => 1,
|
||||
p_status_code => l_status,
|
||||
p_response => l_response
|
||||
);
|
||||
DBMS_OUTPUT.PUT_LINE('Status: ' || l_status);
|
||||
DBMS_OUTPUT.PUT_LINE('Response: ' || l_response);
|
||||
END;
|
||||
/
|
||||
*/
|
||||
Reference in New Issue
Block a user