Send message to user via AJAX ping, for example when BG job finishes

This commit is contained in:
Jan Kvetina 2022-03-11 21:55:43 +01:00
parent 1494246f12
commit 5d2994bd40
6 changed files with 216 additions and 3 deletions

View File

@ -23,7 +23,7 @@ wwv_flow_api.create_page(
,p_required_role=>wwv_flow_api.id(9556407311505078)
,p_page_comment=>'Navigation setup page'
,p_last_updated_by=>'DEV'
,p_last_upd_yyyymmddhh24miss=>'20220306094513'
,p_last_upd_yyyymmddhh24miss=>'20220311201303'
);
wwv_flow_api.create_page_plug(
p_id=>wwv_flow_api.id(24141119524306145)
@ -3300,8 +3300,7 @@ wwv_flow_api.create_page_process(
,p_process_sql_clob=>wwv_flow_string.join(wwv_flow_t_varchar2(
'app.log_action(''PUBLISH_CHANGES'');',
'--',
'DBMS_MVIEW.REFRESH(''NAV_AVAILABILITY_MVW'', ''C'', parallelism => 2);',
'DBMS_MVIEW.REFRESH(''NAV_OVERVIEW_MVW'', ''C'', parallelism => 2);',
'app_actions.refresh_nav_views();',
'--',
'app.log_success();',
''))

View File

@ -0,0 +1,26 @@
prompt --application/shared_components/logic/application_processes/ajax_ping
begin
-- Manifest
-- APPLICATION PROCESS: AJAX_PING
-- Manifest End
wwv_flow_api.component_begin (
p_version_yyyy_mm_dd=>'2021.04.15'
,p_release=>'21.1.7'
,p_default_workspace_id=>9014660246496943
,p_default_application_id=>770
,p_default_id_offset=>0
,p_default_owner=>'CORE'
);
wwv_flow_api.create_flow_process(
p_id=>wwv_flow_api.id(35698122384645663)
,p_process_sequence=>10
,p_process_point=>'ON_DEMAND'
,p_process_type=>'NATIVE_PLSQL'
,p_process_name=>'AJAX_PING'
,p_process_sql_clob=>'app_actions.ajax_ping();'
,p_process_clob_language=>'PLSQL'
,p_security_scheme=>'MUST_NOT_BE_PUBLIC_USER'
);
wwv_flow_api.component_end;
end;
/

View File

@ -17,6 +17,7 @@ prompt --install
@@application/shared_components/logic/application_processes/init_translations.sql
@@application/shared_components/logic/application_processes/init_globals.sql
@@application/shared_components/logic/application_processes/init_filters.sql
@@application/shared_components/logic/application_processes/ajax_ping.sql
@@application/shared_components/logic/application_items/g_curr_owner.sql
@@application/shared_components/logic/application_items/g_footer.sql
@@application/shared_components/logic/application_items/g_today.sql

View File

@ -97,6 +97,19 @@ CREATE OR REPLACE PACKAGE app_actions AS
--
-- Refresh navigation MVW in a background job and inform user
--
PROCEDURE refresh_nav_views (
in_log_id logs.log_id%TYPE,
in_user_id logs.user_id%TYPE,
in_app_id logs.app_id%TYPE
);
--
PROCEDURE refresh_nav_views;
--
-- Save changes on Navigation page
--
@ -475,5 +488,26 @@ CREATE OR REPLACE PACKAGE app_actions AS
in_value_hu translated_messages_overview.value_hu%TYPE
);
--
-- Ping procedure to keep communicate with users via AJAX
--
PROCEDURE ajax_ping;
--
-- Send message to user
--
PROCEDURE send_message (
in_user_id user_messages.user_id%TYPE,
in_message user_messages.message_payload%TYPE,
in_type user_messages.message_type%TYPE := NULL,
in_session_id user_messages.session_id%TYPE := NULL,
in_app_id user_messages.app_id%TYPE := NULL,
in_message_id user_messages.message_id%TYPE := NULL
);
END;
/

View File

@ -220,6 +220,48 @@ CREATE OR REPLACE PACKAGE BODY app_actions AS
PROCEDURE refresh_nav_views (
in_log_id logs.log_id%TYPE,
in_user_id logs.user_id%TYPE,
in_app_id logs.app_id%TYPE
)
AS
BEGIN
DBMS_MVIEW.REFRESH('NAV_OVERVIEW_MVW', 'C', parallelism => 2);
DBMS_MVIEW.REFRESH('NAV_AVAILABILITY_MVW', 'C', parallelism => 2);
--
app_actions.send_message (
in_app_id => in_app_id,
in_user_id => in_user_id,
in_message => 'Materialized views refreshed'
);
--
app.log_success(TO_CHAR(in_log_id));
END;
PROCEDURE refresh_nav_views
AS
v_log_id logs.log_id%TYPE;
v_query VARCHAR2(32767);
BEGIN
v_log_id := app.log_module();
--
app.create_job (
in_job_name => 'RECALC_MVW_NAV',
in_statement => 'app_actions.refresh_nav_views(' || v_log_id || ', ''' || app.get_user_id() || ''', ' || app.get_app_id() || ');'
);
EXCEPTION
WHEN app.app_exception THEN
RAISE;
WHEN OTHERS THEN
app.raise_error();
END;
PROCEDURE save_nav_overview (
in_action CHAR,
in_app_id navigation.app_id%TYPE,
@ -1744,5 +1786,79 @@ CREATE OR REPLACE PACKAGE BODY app_actions AS
app.raise_error();
END;
PROCEDURE ajax_ping
AS
BEGIN
APEX_JSON.OPEN_OBJECT();
--
-- APEX_APPLICATION.G_X01, APEX_APPLICATION.G_X02, APEX_APPLICATION.G_X03
--
APEX_JSON.WRITE('status', 'SUCCESS');
--
FOR c IN (
SELECT m.*
FROM user_messages m
WHERE m.app_id = app.get_app_id()
AND m.user_id = app.get_user_id()
AND (m.session_id = app.get_session_id() OR m.session_id IS NULL)
AND m.delivered_at IS NULL
ORDER BY m.created_at DESC
FETCH FIRST 1 ROWS ONLY
) LOOP
APEX_JSON.WRITE('message', c.message_payload);
APEX_JSON.WRITE('type', c.message_type);
--
UPDATE user_messages m
SET m.delivered_at = SYSDATE
WHERE m.app_id = c.app_id
AND m.user_id = c.user_id
AND m.message_id = c.message_id;
END LOOP;
--
APEX_JSON.CLOSE_OBJECT();
EXCEPTION
WHEN app.app_exception THEN
RAISE;
WHEN OTHERS THEN
app.raise_error();
END;
PROCEDURE send_message (
in_user_id user_messages.user_id%TYPE,
in_message user_messages.message_payload%TYPE,
in_type user_messages.message_type%TYPE := NULL,
in_session_id user_messages.session_id%TYPE := NULL,
in_app_id user_messages.app_id%TYPE := NULL,
in_message_id user_messages.message_id%TYPE := NULL
)
AS
v_log_id logs.log_id%TYPE;
BEGIN
v_log_id := app.log_module();
--
INSERT INTO user_messages (app_id, user_id, message_id, message_type, message_payload, session_id, created_at, created_by)
VALUES (
COALESCE(in_app_id, app.get_app_id()),
in_user_id,
COALESCE(in_message_id, log_id.NEXTVAL),
COALESCE(in_type, 'SUCCESS'),
in_message,
in_session_id,
SYSDATE,
app.get_user_id()
);
--
app.log_success();
EXCEPTION
WHEN app.app_exception THEN
RAISE;
WHEN OTHERS THEN
app.raise_error();
END;
END;
/

37
tables/user_messages.sql Normal file
View File

@ -0,0 +1,37 @@
--DROP TABLE user_messages PURGE;
CREATE TABLE user_messages (
app_id NUMBER(4) CONSTRAINT nn_user_messages_app_id NOT NULL,
user_id VARCHAR2(30) CONSTRAINT nn_user_messages_user_id NOT NULL,
message_id INTEGER CONSTRAINT nn_user_messages_message_id NOT NULL, -- log_id
message_type VARCHAR2(16),
message_payload VARCHAR2(2000),
session_id INTEGER,
--
created_by VARCHAR2(30),
created_at DATE,
delivered_at DATE,
--
CONSTRAINT pk_user_messages
PRIMARY KEY (app_id, user_id, message_id),
--
CONSTRAINT fk_user_messages_app_id
FOREIGN KEY (app_id)
REFERENCES apps (app_id),
--
CONSTRAINT fk_user_messages_user_id
FOREIGN KEY (user_id)
REFERENCES users (user_id)
DEFERRABLE INITIALLY DEFERRED
)
STORAGE (BUFFER_POOL KEEP);
--
COMMENT ON TABLE user_messages IS '[CORE] Messages for users';
--
COMMENT ON COLUMN user_messages.app_id IS 'APEX application ID';
COMMENT ON COLUMN user_messages.user_id IS 'User ID from USERS table';
COMMENT ON COLUMN user_messages.message_id IS 'Message id';
COMMENT ON COLUMN user_messages.message_type IS 'Message type';
COMMENT ON COLUMN user_messages.message_payload IS 'Message itself';
COMMENT ON COLUMN user_messages.session_id IS 'Session id';
COMMENT ON COLUMN user_messages.delivered_at IS 'Stamp of delivery';