asyncModule.tellMeSomething = (callback) => { process.nextTick(() => { if(!asyncModule.initialized) { return callback(newError("I don't have anythins to say right now")); } callback(null, `Current time is: ${newDate()}`); }); };
通常我們使用 Node.js 開發的專案最後都會將它佈署到 Linux 伺服器上,而 Linux 伺服器通常都不會安裝 GUI 操作介面,有時想要簡單的>更改檔案的內容,對於 vi 又不熟悉,實在是大費周章。這裡就示範如何使用 Windows 上的 VS Code 連線到 Linux 伺服器,直接修改 Linux 伺服器上的檔案。如有必要,也可直接下 Linux 指令。
VS Code Remote-SSH Extension
這裡要使用的是 VS Code 的 Remote-SSH Extension。
安裝了 Remote-SSH Extension 之後 VS Code 的左下角會出現一個符號。
按一下這個符號,VS Code 上方會出現所要選擇使用的功能。
這裡選擇 Remote-SSH: Connect to Host… 這會開啟另外一個 Window 視窗,然後要求你輸入使用者與伺服器名稱。
如果 VS Code 無法自動檢測到您要連接的服務器的類型,會要求您手動選擇類型。
輸入密碼。
如果連線成功,左下角的 Status 將會出現連線的伺服器。
現在你可以使用 VS Code 打開文件夾。
選擇文件夾,然後按 OK。
每次選擇一個新的文件夾都會要求你再度輸入密碼。
現在你可以像使用 Local 端的檔案夾一樣,使用 VS Code 編輯檔案。
你也可以開啟一個終端螢幕。
可以使用這個終端螢幕下 Linux 伺服器指令,就像使用 Putty 連到 Linux 伺服器一樣。
是的! 你沒有看錯標題。Oracle AQ 也跨出了資料庫。在 node-oracledb 4.0 中引入了用於 AQ 的 Node-oracledb API。
Oracle AQ 的運作已有一段時間了,基本運作方式大家都很熟了,這裡直接看範例,讓 AQ 走出 Oracle 資料庫。
Create and Start Queue
1 2 3 4 5 6
/* For the data we want to queue */ CREATEORREPLACETYPE demo_msg_type ASOBJECT ( subject VARCHAR2(30), textVARCHAR2(100) ) /
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
-- Create and start a queue BEGIN DBMS_AQADM.CREATE_QUEUE_TABLE( QUEUE_TABLE => 'DEMO.DEMO_MSG_QUEUE_TAB', QUEUE_PAYLOAD_TYPE => 'DEMO.DEMO_MSG_TYPE');
WoT (Web of Things) 是 IoT (Internet of Things 物聯網) 的 Application 層,就是使用 Web 技術來打造 application。也就是說,IoT + Web-enabled technologies 就是 WoT。對 WoT 來說,最重要的觀念,就是以 URL 來表示 IoT 裝置;為 IoT 加入 URL 的觀念,就是 Google 提出的 Physical Web 計畫。
未來每個物件 (Objects) 全部都會和 Web 結合, 而首要條件就是所謂的 Things 必須是可以和 Web 溝通的裝置, 這些智慧裝置之間也能透過 Web 標準來互相溝通。WoT 重點在於使用 Web 的軟體標準和框架, 例如 REST, HTTP 和 URI 來建立應用程式以及服務, 並和其他裝置做溝通, 簡單來說就是日常生活所有的東西都可以存取 Web, 就是 WoT 的精隨。
除了能夠相互溝通,時間性當然也很重要,Real-time 數據越來越受歡迎。基本思路很簡單: 當物件發生變化時,任何查看物件數據的客戶端都應立即能看得到異動。最初,在 Web 應用程式中模擬 real-time 數據的唯一方法是從瀏覽器每隔一段固定的時間不斷循環的從 Web 服務器抓取資料 (Polling)。 這通常很複雜,難以擴大應用。WebSocket,改變了這種狀況,這是一種以高效率的方式在瀏覽器和 Web 服務器之間提供雙向通信的協議。
SQL> desc CQ_NOTIFICATION$_DESCRIPTOR Name Null? Type ----------------------------------------------------- -------- ------------------------------------ REGISTRATION_ID NUMBER TRANSACTION_ID RAW(8) DBNAME VARCHAR2(30) EVENT_TYPE NUMBER NUMTABLES NUMBER TABLE_DESC_ARRAY SYS.CHNF$_TDESC_ARRAY QUERY_DESC_ARRAY
SQL> desc CQ_NOTIFICATION$_TABLE Name Null? Type ----------------------------------------------------- -------- ------------------------------------ OPFLAGS NUMBER TABLE_NAME VARCHAR2(64) NUMROWS NUMBER ROW_DESC_ARRAY SYS.CHNF$_RDESC_ARRAY
SQL> desc CQ_NOTIFICATION$_QUERY Name Null? Type ----------------------------------------------------- -------- ------------------------------------ QUERYID NUMBER QUERYOP NUMBER TABLE_DESC_ARRAY SYS.CHNF$_QDESC_ARRAY
SQL> desc CQ_NOTIFICATION$_ROW Name Null? Type ----------------------------------------------------- -------- ------------------------------------ OPFLAGS NUMBER ROW_ID VARCHAR2(2000)
/* Body of loop does not run when l_numrows is zero. */ FOR k IN 1..l_numrows LOOP /* loop over rows */ /* 影響的每筆及它的 ROWID。可使用 ROWID 讀取該筆資料,這應是你需要處理的地方。*/ l_row_id := ntfnds.query_desc_array(i).table_desc_array(j).row_desc_array(k).row_id;
/* 註冊的 Query,當所有會影響此段 Query 結果的異動,都會觸發事件發出通知(Notification)。 這裡可以註冊多段的 Query。 */ OPEN v_cursor FOR SELECT dbms_cq_notification.CQ_NOTIFICATION_QUERYID, sal, comm FROM DEMO.EMP WHERE deptno = 10;
CLOSE v_cursor;
DBMS_CQ_NOTIFICATION.reg_end; END; /
註冊的 Query 牽涉到 Emp Table 的 sal、comm 與 deptno 欄位。
查詢已經註冊的事件處理程式:
1 2 3
select regid, table_name, callback from user_change_notification_regs /
SQL> desc tickers_nt; tickers_nt TABLE OF TICKER_OT Name Null? Type ----------------------------------------- -------- ---------------------------- TICKER VARCHAR2(20) PRICEDATE DATE PRICETYPE VARCHAR2(1) PRICE NUMBER
SQL> desc tickers; Name Null? Type ----------------------------------------- -------- ---------------------------- TICKER VARCHAR2(20) PRICEDATE DATE PRICETYPE VARCHAR2(1) PRICE NUMBER
這裡打算在 Table function 使用資料流式的處理(Streaming process)。 意思是將從 SQL 傳遞一組數據 (rows and columns)到 table function。為此,需要定義一個強型態 (strong) 的 REF CURSOR 類型,該類型將用作接受 SQL 語句內數據集的函數參數的數據類型。
DECLARE TYPE rc ISREFCURSOR; /* 弱型態 CURSOR */ CURSOR c IS SELECT * FROM dual; /* 靜態的 (static) */ l_cursor rc; BEGIN IF (TO_CHAR(SYSDATE, 'dd') = 30) THEN/* 弱型態 REF CURSUR 可以是 */ OPEN l_cursor FOR'SELECT * FROM emp'; /* static SQL 或 dynamic SQL statement*/ ELSIF (TO_CHAR(SYSDATE, 'dd') = 29) THEN OPEN l_cursor FOR SELECT * FROM dept; ELSE OPEN l_cursor FOR SELECT * FROM dual; ENDIF; OPEN C; END; /
無論運行多少次,CURSOR c 始終是 “SELECT * FROM dual”。 REF CURSOR 則可以是任何東西,而且可以是 static SQL 或 dynamic SQL statement。
CREATEORREPLACEFUNCTION employee_pl(deptno_in NUMBERDEFAULTNULL) RETURN employee_nt PIPELINED AUTHID DEFINER IS CURSOR c1 IS SELECT e.empno, e.ename, e.sal, e.comm, d.dname FROM emp e, dept d WHERE e.deptno = d.deptno AND e.deptno = coalesce(deptno_in, e.deptno) ORDERBY e.empno; BEGIN FOR rec IN c1 LOOP PIPEROW(employee_ot(rec.empno, rec.ename, 'S', rec.sal, rec.dname)); PIPE ROW(employee_ot(rec.empno, rec.ename, 'C', rec.comm, rec.dname)); ENDLOOP; RETURN; END; /
1
select * fromtable(employee_pl(30));
EMPNO ENAME I INCOME_VALUE DNAME ---------- ---------- - ------------ -------------- 7499 ALLEN S 1600 SALES 7499 ALLEN C 303 SALES 7654 葉習堃 S 1250 SALES 7654 葉習堃 C 1400 SALES 7698 BLAKE S 2850 SALES 7698 BLAKE C 101 SALES 7844 하찮고 S 1500 SALES 7844 하찮고 C SALES 7900 JAMES S 94998 SALES 7900 JAMES C SALES
EMPNO ENAME I INCOME_VALUE DNAME ---------- ---------- - ------------ -------------- 7369 SMITH S 8001 RESEARCH 7369 SMITH C RESEARCH 7499 ALLEN S 1600 SALES 7499 ALLEN C 303 SALES
EMPNO ENAME I INCOME_VALUE DNAME ---------- ---------- - ------------ -------------- 7369 SMITH S 8001 RESEARCH 7369 SMITH C RESEARCH 7499 ALLEN S 1600 SALES 7499 ALLEN C 303 SALES
CREATEORREPLACEFUNCTION strings (err_in INVARCHAR2) RETURN strings_t PIPELINED AUTHID DEFINER IS BEGIN PIPEROW (1); CASE err_in WHEN 'no_data_found' THEN RAISE NO_DATA_FOUND; WHEN 'no_data_needed' THEN RAISE NO_DATA_NEEDED; WHEN 'program_error' THEN RAISE PROGRAM_ERROR; ENDCASE; RETURN; END; /
這段程式碼中我們故意引發錯誤,觀察 SQL 的回應。
SQL> select COLUMN_VALUE my_string from table(strings('no_data_found'));
在之前,我們使用 API key 作為身份驗證類型創建了 GraphQL API。 這在某些情況下是很好的,例如當你想讓應用程序的所有用戶都可以使用 GraphQL 查詢時。
除了 API key 外,AppSync 支援四種主要的身份驗證方法:
The API key 使用 API key 時,要在發出 HTTP 請求時,在 header 以 x-api-key 的形式發送 API key。 如果使用 Amplify 客戶端,則會自動發送。
Amazon Cognito user pools 在這個範例,我們要使用 Amazon Cognito 的身份驗證託管服務。 使用 Amazon Cognito,我們可以針對 API 本身以及 GraphQL 類型和字段的存取,做進階的權限和群組的控管。
OpenID Connect OpenID Connect 使你能夠使用自己的身份驗證提供者。因此,如果你喜歡其他身份驗證服務(如 Auth0),或者你的公司具有自己的身份驗證方式,則仍可以使用它來對 AppSync API 進行身份驗證。
IAM AWS IAM 類型會在 GraphQL API 上使用 AWS Signature Version 4 簽章過程。您可以使用 Cognito identity pools 中未經身份驗證的 IAM 角色給予 public 的存取權限,這會比使用 API key 啟用 public 的存取權限更安全。
這裡,我們將結合使用 API key 和 Amazon Cognito 為 API 提供的多種身份驗證類型,從而實現公共讀取和私有存取的權限控管。
授權
使用 GraphQL Transform 程式庫,我們還可以使用 @auth 指令為 API 定義不同的授權規則。
Do you want to use the default authentication and security configuration? Default configuration How do you want users to be able to sign in? Username Do you want to configure advanced settings? Yes, I want to make some additional changes. What attributes are required for signing up? Email Do you want to enable any of the following capabilities? Add User to Group ? Enter the name of the group to which users will be added. Admin ? Do you want to edit your add-to-group function now? Yes
? Please select from one of the below mentioned services: GraphQL ? Provide API name: festivalapi ? Choose the default authorization type for the API Amazon Cognito User Pool Use a Cognito user pool configured as a part of this project. ? Do you want to configure advanced settings for the GraphQL API Yes, I want to make some additional changes. ? Configure additional auth types? Yes ? Choose the additional authorization types you want to configure for the API API key API key configuration ? Enter a description for the API key: public ? After how many days from now the API key should expire (1-365): 365 ? Configure conflict detection? No ? Do you have an annotated GraphQL schema? No ? Choose a schema template: Single object with fields (e.g., “Todo” with ID, name, description) ? Do you want to edit the schema now? (y/N) Yes
fetchPerformanceInfo 函式使用路由參數中的 id 來調用 AppSync API。 這裡的 API 調用使用 API.graphql,傳入 variables,query 和 authMode。 預設情況下,這裡的 API 使用 Cognito User Pools 作為身份驗證模式。 每當我們想覆蓋此預設 (例如在這裡的情況下進行 public API 調用) 時,我們需要在 API 調用本身中指定 authMode。
從 API 返回數據後,我們調用 setLoading 和 setPerformance 來更新 UI 以呈現從 API 返回的數據。
Strings: eq | ne | le | lt | ge | gt | contains | notContains | beginsWith | between
Numbers: eq | ne | le | lt | ge | gt | between
Lists: contains | notContains
例如,如果要獲取 title 包含 “Hello” 的所有訊息的列表:
1 2
const messages = await DataStore .query(Message, m => m.title('contains', 'Hello'))
? Please select from one of the below mentioned services: GraphQL ? Provide API name: rtmessageboard ? Choose the default authorization type for the API API key ? Enter a description for the API key: public ? After how many days from now the API key should expire (1-365): 365 ? Do you want to configure advanced settings for the GraphQL API Yes, I want to make some additional changes. ? Configure additional auth types? No ? Configure conflict detection? Yes ? Select the default resolution strategy Auto Merge ? Do you have an annotated GraphQL schema? No ? Choose a schema template: Single object with fields (e.g., “Todo” with ID, name, description) ? Do you want to edit the schema now? Yes