Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

Làm thế nào để sử dụng Oracle DBMS_ALERT trong Oracle APEX?

Tôi đã thiết lập một bản demo trên apex.oracle.com, nhưng vì bạn cần một khoản trợ cấp thực thi trên dbms_alert, nó sẽ phải ở dạng chỉ văn bản.

Bạn có thể đi khá xa với toàn bộ thiết lập, vì vậy tôi coi đây là điều cơ bản để xây dựng. Ví dụ:tôi chỉ làm việc với một cảnh báo. Trong mẫu của bạn, bạn có thể muốn sử dụng nhiều sự kiện để nắm bắt các cảnh báo tiến trình khác nhau. Điều này là vì lý do đơn giản là để trả lại một cái gì đó cho máy khách (phản hồi ajax), lệnh gọi lại ajax phải 'đóng'. Vì vậy, khi bắt được một cảnh báo và muốn trả lại cảnh báo đó, bạn cần ghi vào bộ đệm và nó cần được trả lại. Điều này có nghĩa là bạn cũng sẽ ngừng nghe sự kiện (đọc:in apex, you should!).

Hãy xem xét quy trình như thế này:bạn sẽ thực hiện một cuộc gọi ajax và có một quy trình gọi lại ajax ghi lại sự quan tâm trong một sự kiện. Sau đó, bạn chờ một cảnh báo xảy ra. Bạn bắt nó và trả lại bằng cách ghi nó vào bộ đệm http (htp.p ). Đó là phần cuối của mã và apex sẽ xóa bộ đệm, lệnh gọi ajax sau đó sẽ nhận phản hồi và bạn sẽ có thể quản lý kết quả trả về đó.
Tuy nhiên, đừng quên:apex sử dụng gộp kết nối và cơ sở dữ liệu các phiên không được liên kết trực tiếp mà được sử dụng lại mọi lúc. Bạn không muốn 'rời khỏi' một phiên cơ sở dữ liệu 'bẩn'. Bạn cũng sẽ phải hủy đăng ký sở thích cảnh báo của mình. Điều này cũng tạo ra một trường hợp sử dụng ID duy nhất cho cảnh báo - cảnh báo có thể được đăng ký trong các phiên (cơ sở dữ liệu) khác nhau, vì vậy nếu đây sẽ là trang mà nhiều người dùng có thể sử dụng để theo dõi tiến trình xử lý của họ, bạn không muốn họ can thiệp vào cảnh báo của người dùng khác.

Tuy nhiên, bản chất quan tâm thoáng qua này cũng có nghĩa là sẽ có "sự gián đoạn" giữa các cuộc gọi ajax khác nhau được thực hiện. Khi bạn muốn nghe nhiều cảnh báo và những cảnh báo này có thể được đóng gói rất chặt chẽ với nhau, bạn có thể bỏ lỡ một cơ hội tồn tại. Giả sử 2 cảnh báo cách nhau 1ms:cảnh báo đầu tiên sẽ bị bắt, được báo cáo cho cuộc gọi ajax, sẽ phải bắt đầu cuộc gọi mới ngay lập tức để nghe thêm cảnh báo. Nhưng vì không có người nghe hoạt động trong thời gian ngắn đó, cảnh báo tiếp theo có thể đã bị bỏ lỡ. Bây giờ - đây có thể chỉ là vấn đề khi bạn kích hoạt nhiều cảnh báo trong cùng một trình xử lý. Nếu bạn sử dụng nhiều trình xử lý và bắt đầu lệnh gọi ajax cho tất cả những trình xử lý đó cùng một lúc, tất cả chúng sẽ được xử lý kịp thời. Tất nhiên, có những giải pháp cho cả hai. Tôi tưởng tượng rằng khi chỉ sử dụng một trình xử lý, bạn có thể bắt tất cả các cảnh báo trong một bộ sưu tập và kiểm tra xem bạn đã gửi phản hồi cho một cảnh báo nhất định hay chưa và có nên tiếp tục đăng ký hay không. Với nhiều trình xử lý, bạn có thể sử dụng một id duy nhất và gắn nó với các trạng thái khác nhau.

Vì vậy, đây là một số mã thực tế mà tôi đã sử dụng trong POC cục bộ của mình.

Tổng quan:Tôi có 3 nút:1 để tạo id cảnh báo, tôi đã sử dụng một chuỗi. Một nút khác để bắt đầu lắng nghe một sự kiện và một nút khác để gửi cảnh báo.

Mã JS cho nút NEW_ALERT_ID:

apex.server.process("NEW_ALERT").done(function(pdata){
$s("P1_ALERT_ID",pdata.alertId);
})

Mã JS cho nút START_LISTEN:

apex.server.process("LISTEN_ALERT",{x01:$v("P1_ALERT_ID")},{timeout:(31*1000)})
.done(function(pdata){
  if (pdata.success ){
      alert('Caught alert: ' + pdata.message);
  } else {
      alert("No alerts caught during wait on database. You may want to continue listening in...")
  }
})
.fail(function(jqXHR, textStatus){
    if(textStatus === 'timeout')
    {     
        alert('Call should have returned by now...'); 
        //do something. Try again perhaps?
    }
});

Mã JS cho nút SEND_ALERT:

apex.server.process("SEND_ALERT",{x01:$v("P1_ALERT_ID")},{dataType:"text"});

Các quy trình gọi lại AJAX:

NEW_ALERT:

htp.p('{"alertId":'||alert_seq.nextval()||'}');

LISTEN_ALERT:

declare
  alert_id number := apex_application.g_x01;
  msg varchar2(2000);
  stat pls_integer;
  keep_looping boolean := true;
  insurance binary_integer := 0; -- prevent an infinite loop

  onecycle binary_integer := 3; -- one cycle of waiting, in seconds
  maxcycles binary_integer := 10; -- in this session, the max amount of cycles to wait
begin
  dbms_alert.register(alert_id);

  while keep_looping
  loop
    insurance := insurance + 1;

    dbms_alert.waitone(alert_id, msg, stat, onecycle);
    if stat = 1 then
      apex_debug.message('timeout occured, going again');
    else
      apex_debug.message('alert: '||msg);
      keep_looping := false;
    end if;

    exit when insurance = maxcycles;    
  end loop;


  if keep_looping then
    -- we waited a really long time now. It may be a good idea to return this info to the client and let it start a new call
    htp.p('{"success":false,"message":"No alert during wait on database"}');
  else
    htp.p('{"success":true,"message":"'||msg||'"}');
  end if;
end;

SEND_ALERT:

declare
  alert_id number := apex_application.g_x01;
begin
  dbms_alert.signal(alert_id, 'alert sent at '||to_char(systimestamp, 'HH24:MI:SS FF6'));
end;

Vì vậy, trước tiên tôi sẽ nhận được một ID cảnh báo, sau đó tôi sẽ bắt đầu lắng nghe, và sau đó vào một thời điểm nào đó, tôi sẽ gửi một cảnh báo (hoặc không). Tuy nhiên, đó là một bộ xương và sẽ cần được tinh chỉnh thêm trong thiết lập thực tế của bạn.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. nếu (chọn số (cột) từ bảng)> 0 thì

  2. Trình hướng dẫn mô hình dữ liệu thực thể có ngoại lệ khi cố gắng thêm kết nối Oracle mới

  3. làm cách nào để sử dụng chuỗi kết nối cùng với url jdbc

  4. Sử dụng cơ sở dữ liệu Oracle với CakePHP 2.0

  5. Chuyển đổi số màu âm thành HEX hoặc RGB