檢視原始碼 erpc (核心 v10.2)
增強型遠端程序呼叫
此模組提供類似遠端程序呼叫的服務。遠端程序呼叫是一種在遠端節點上呼叫函數並收集答案的方法。它用於收集遠端節點上的資訊,或在遠端節點上執行具有特定副作用的函數。
這是 rpc
模組提供的操作的增強子集。所謂的增強,是指它可以區分傳回值、引發的異常和其他錯誤。erpc
也比原始的 rpc
實作具有更好的效能和可擴展性。然而,目前的 rpc
模組將在可能的情況下利用 erpc
來提供這些特性。
為了使 erpc
操作成功,遠端節點也需要支援 erpc
。通常只有 OTP 23 的普通 Erlang 節點才支援 erpc
。
請注意,使用者有責任確保在相關節點上可以使用透過 erpc
執行的正確程式碼。
注意
關於分散式訊號的一些重要資訊,請參閱《Erlang 參考手冊》中「程序」章節的「分散式上的封鎖訊號」部分。封鎖訊號可能會導致
erpc
中的逾時顯著延遲。
摘要
類型
不透明的請求識別碼。有關更多資訊,請參閱 send_request/4
。
不透明的請求識別碼集合(request_id/0
),其中每個請求識別碼都可以與使用者選擇的標籤相關聯。有關更多資訊,請參閱 reqids_new/0
。
erpc 函數使用的逾時時間。
函數
在節點 Node
上評估 apply(Module, Function, Args)
並傳回對應的值 Result
。Timeout
設定 call
操作完成的最長時間限制。
在節點 Node
上評估 apply(Module, Function, Args)
。不會將回應傳遞給呼叫程序。cast()
在發送 cast 請求後立即傳回。除了錯誤的引數之外,任何失敗都會被靜默忽略。
檢查訊息是否是對呼叫程序先前使用 send_request/4
發出的 call
請求的回應。
檢查訊息是否是對應於儲存在 RequestIdCollection
中的請求識別碼的 call
請求的回應。RequestIdCollection
的所有請求識別碼都必須對應於使用 send_request/4
或 send_request/6
發出的請求,且所有請求都必須由呼叫此函數的程序發出。
在多個節點上平行執行多個 call
操作。
在節點 Nodes
上評估 apply(Module, Function, Args)
。不會將回應傳遞給呼叫程序。multicast()
在發送 cast 請求後立即傳回。除了錯誤的引數之外,任何失敗都會被靜默忽略。
接收對呼叫程序先前使用 send_request/4
發出的 call
請求的回應。
接收對應於儲存在 RequestIdCollection
中的請求識別碼的 call
請求的回應。RequestIdCollection
的所有請求識別碼都必須對應於使用 send_request/4
或 send_request/6
發出的請求,且所有請求都必須由呼叫此函數的程序發出。
儲存 RequestId
並將 Label
與請求識別碼相關聯,方法是將此資訊新增至 RequestIdCollection
並傳回產生的請求識別碼集合。
傳回新的空請求識別碼集合。可以使用請求識別碼集合來處理多個未完成的請求。
傳回儲存在 RequestIdCollection
中的請求識別碼數量。
傳回一個 {RequestId, Label}
元組列表,該列表對應於 RequestIdCollection
集合中存在的所有帶有相關聯標籤的請求識別碼。
將非同步 call
請求發送至節點 Node
。
將非同步 call
請求發送至節點 Node
。Label
將與操作的請求識別碼相關聯,並新增至傳回的請求識別碼集合 NewRequestIdCollection
。稍後可以使用該集合,方法是將該集合作為引數傳遞給 receive_response/3
、wait_response/3
或 check_response/3
,從而取得與集合中請求對應的一個回應。
等同於 erpc:wait_response(RequestId, 0)
。也就是說,輪詢呼叫程序先前發出的 call
請求的回應訊息。
等待或輪詢呼叫程序先前使用 send_request/4
發出的 call
請求的回應訊息。
等待或輪詢對應於儲存在 RequestIdCollection
中的請求識別碼的 call
請求的回應。RequestIdCollection
的所有請求識別碼都必須對應於使用 send_request/4
或 send_request/6
發出的請求,且所有請求都必須由呼叫此函數的程序發出。
類型
-opaque request_id()
不透明的請求識別碼。有關更多資訊,請參閱 send_request/4
。
-opaque request_id_collection()
不透明的請求識別碼集合(request_id/0
),其中每個請求識別碼都可以與使用者選擇的標籤相關聯。有關更多資訊,請參閱 reqids_new/0
。
-type timeout_time() :: 0..4294967295 | infinity | {abs, integer()}.
erpc 函數使用的逾時時間。
值可以是
0..4294967295
- 相對於目前時間的逾時時間(以毫秒為單位)。infinity
- 無限逾時。也就是說,操作永遠不會逾時。{abs, Timeout}
- 以毫秒為單位的絕對 Erlang 單調時間逾時。也就是說,當erlang:monotonic_time(millisecond)
傳回的值大於或等於Timeout
時,操作將逾時。不允許Timeout
指定未來超過4294967295
毫秒的時間。當您擁有對應於完整請求集合的回應的截止時間時(request_id_collection/0
),使用絕對逾時值識別逾時時間特別方便,因為您不必一遍又一遍地重新計算直到截止時間的相對時間。
函數
-spec call(Node, Fun, Timeout) -> Result when Node :: node(), Fun :: function(), Timeout :: timeout_time(), Result :: term().
等同於 erpc:call(Node, erlang, apply, [Fun,[]], Timeout)
。
可能會拋出與 call/5
相同的例外,此外,如果 Fun
不是零元函數,則會拋出 {erpc, badarg}
error
例外。
-spec call(Node, Module, Function, Args, Timeout) -> Result when Node :: node(), Module :: atom(), Function :: atom(), Args :: [term()], Timeout :: timeout_time(), Result :: term().
在節點 Node
上評估 apply(Module, Function, Args)
並傳回對應的值 Result
。Timeout
設定 call
操作完成的最長時間限制。
只有在應用函數成功返回且未拋出任何未捕獲的例外、操作未超時且未發生任何故障時,call()
函數才會返回。在所有其他情況下,都會拋出例外。以下例外(按例外類別列出)目前可能會由 call()
拋出
throw
- 應用函數呼叫了throw(Value)
且未捕獲此例外。例外原因Value
等於傳遞給throw/1
的參數。exit
- 例外原因{exception, ExitReason}
- 應用函數呼叫了exit(ExitReason)
且未捕獲此例外。退出原因ExitReason
等於傳遞給exit/1
的參數。{signal, ExitReason}
- 應用函數的進程接收到退出信號並因該信號而終止。進程以退出原因ExitReason
終止。
error
- 例外原因{exception, ErrorReason, StackTrace}
- 在應用函數時發生了導致拋出錯誤例外的執行階段錯誤,且應用函數未捕獲此例外。錯誤原因ErrorReason
表示發生的錯誤類型。StackTrace
的格式與在try/catch
結構中捕獲時相同。StackTrace
僅限於應用函數及其呼叫的函數。{erpc, ERpcErrorReason}
-erpc
操作失敗。以下ERpcErrorReason
是最常見的幾種badarg
- 如果以下任何一項為真Node
不是一個原子。Module
不是一個原子。Function
不是一個原子。Args
不是一個列表。請注意,該列表在客戶端沒有被驗證為正確的列表。Timeout
無效。
noconnection
- 與Node
的連線遺失或無法建立。該函數可能會或可能不會被應用。system_limit
- 由於達到某些系統限制,erpc
操作失敗。這通常是因為無法在遠端節點Node
上建立進程,但也可能是其他原因。timeout
-erpc
操作超時。該函數可能會或可能不會被應用。notsup
- 遠端節點Node
不支援此erpc
操作。
如果 erpc
操作失敗,但不知道該函數是否已/將被應用(即,超時或連線遺失),則如果/當應用函數完成時,呼叫者不會收到任何關於結果的進一步資訊。如果應用函數明確地與呼叫進程通信,那麼此通信當然可能會到達呼叫進程。
注意
您不能對執行
apply()
的進程做*任何*假設。它可能是呼叫進程本身、伺服器或新產生的進程。
等同於 erpc:cast(Node,erlang,apply,[Fun,[]])
。
如果出現以下情況,cast/2
將會失敗並拋出 {erpc, badarg}
error
例外
Node
不是一個原子。Fun
不是一個零元函數。
-spec cast(Node, Module, Function, Args) -> ok when Node :: node(), Module :: atom(), Function :: atom(), Args :: [term()].
在節點 Node
上評估 apply(Module, Function, Args)
。不會將回應傳遞給呼叫程序。cast()
在發送 cast 請求後立即傳回。除了錯誤的引數之外,任何失敗都會被靜默忽略。
如果出現以下情況,cast/4
將會失敗並拋出 {erpc, badarg}
error
例外
Node
不是一個原子。Module
不是一個原子。Function
不是一個原子。Args
不是一個列表。請注意,該列表在客戶端沒有被驗證為正確的列表。
注意
您不能對執行
apply()
的進程做*任何*假設。它可能是伺服器或新產生的進程。
-spec check_response(Message, RequestId) -> {response, Result} | no_response when Message :: term(), RequestId :: request_id(), Result :: term().
檢查訊息是否是對呼叫程序先前使用 send_request/4
發出的 call
請求的回應。
RequestId
應為先前發出的 send_request/4
呼叫所返回的值,且對應的回應不應已被 check_response/2
、receive_response/2
或 wait_response/2
接收並處理完成。Message
是要檢查的訊息。
如果 Message
與回應不符,則會返回原子 no_response
。如果 Message
與回應相符,則 call
操作完成,並返回結果,格式為 {response, Result}
,其中 Result
對應於應用函數返回的值,或拋出例外。可能拋出的例外與 call/4
可能拋出的例外相同。也就是說,不會拋出 {erpc, timeout}
error
例外。如果偵測到無效的 RequestId
,check_response()
將會失敗並拋出 {erpc, badarg}
例外。
如果 erpc
操作失敗,但不知道該函數是否已/將被應用(即,連線遺失),則如果/當應用函數完成時,呼叫者不會收到任何關於結果的進一步資訊。如果應用函數明確地與呼叫進程通信,那麼此通信當然可能會到達呼叫進程。
-spec check_response(Message, RequestIdCollection, Delete) -> {{response, Result}, Label, NewRequestIdCollection} | no_response | no_request when Message :: term(), RequestIdCollection :: request_id_collection(), Delete :: boolean(), Result :: term(), Label :: term(), NewRequestIdCollection :: request_id_collection().
檢查訊息是否是對應於儲存在 RequestIdCollection
中的請求識別碼的 call
請求的回應。RequestIdCollection
的所有請求識別碼都必須對應於使用 send_request/4
或 send_request/6
發出的請求,且所有請求都必須由呼叫此函數的程序發出。
Label
是與回應對應的請求的請求識別碼關聯的標籤。當在 請求識別碼集合中 加入請求識別碼時,或使用 send_request/6
發送請求時,請求識別碼會與標籤關聯。
與 check_response/2
相比,與特定請求識別碼關聯的返回結果或與特定請求識別碼關聯的例外將會被包裝在 3 元組中。此元組的第一個元素等於 check_response/2
會產生的值,第二個元素等於與特定請求識別碼關聯的 Label
,第三個元素 NewRequestIdCollection
是一個可能修改過的請求識別碼集合。error
例外 {erpc, badarg}
不與任何特定請求識別碼關聯,因此不會被包裝。
如果 RequestIdCollection
為空,則會返回原子 no_request
。如果 Message
與 RequestIdCollection
中的任何請求識別碼不符,則會返回原子 no_response
。
如果 Delete
等於 true
,則在產生的 NewRequestIdCollection
中,與 Label
的關聯將已從 RequestIdCollection
中刪除。如果 Delete
等於 false
,則 NewRequestIdCollection
將等於 RequestIdCollection
。請注意,刪除關聯並非免費,且包含已處理請求的集合仍然可以被後續對 check_response/3
、receive_response/3
和 wait_response/3
的呼叫使用。然而,如果沒有刪除已處理的關聯,則上述呼叫將無法偵測到何時沒有更多待處理的請求需要處理,因此您必須以其他方式追蹤此資訊,而不是依賴 no_request
返回。請注意,如果您將僅包含已處理或已放棄請求的關聯的集合傳遞給 check_response/3
,它將始終返回 no_response
。
請注意,回應可能會在 {erpc, badarg}
例外發生時被消耗,如果是這樣,則將永遠遺失。
-spec multicall(Nodes, Fun, Timeout) -> Result when Nodes :: [atom()], Fun :: function(), Timeout :: timeout_time(), Result :: term().
等同於 erpc:multicall(Nodes, erlang, apply, [Fun,[]], Timeout)
。
可能拋出與 multicall/5
相同的例外,此外,如果 Fun
不是零元函數,則會拋出 {erpc, badarg}
error
例外。
-spec multicall(Nodes, Module, Function, Args, Timeout) -> Result when Nodes :: [atom()], Module :: atom(), Function :: atom(), Args :: [term()], Timeout :: timeout_time(), Result :: [{ok, ReturnValue :: term()} | caught_call_exception()].
在多個節點上平行執行多個 call
操作。
也就是說,在節點 Nodes
上並行評估 apply(Module, Function, Args)
。Timeout
設定所有 call
操作完成的上限時間。結果會以列表形式返回,其中每個節點的結果都放置在 Nodes
中節點名稱所在的位置。結果列表中的每個項目格式如下:
{ok, Result}
- 此特定節點的call
操作返回Result
。{Class, ExceptionReason}
- 此特定節點的call
操作拋出了類別為Class
,例外原因為ExceptionReason
的例外。這些對應於call/5
可能拋出的例外。
如果發生以下情況,multicall/5
會失敗並拋出 {erpc, badarg}
error
例外:
Nodes
不是合適的原子列表。請注意,在發生失敗時,某些請求可能已經發送。也就是說,該函數可能在某些節點上應用,也可能沒有。Module
不是一個原子。Function
不是一個原子。Args
不是一個列表。請注意,該列表在客戶端沒有被驗證為正確的列表。
呼叫 erpc:multicall(Nodes, Module, Function, Args)
等同於呼叫 erpc:multicall(Nodes, Module, Function, Args, infinity)
。如果忽略效能和失敗行為,這些呼叫也等同於呼叫以下的 my_multicall(Nodes, Module, Function, Args)
。multicall()
可以利用選擇性接收最佳化,從而無需從頭開始掃描訊息佇列以尋找匹配的訊息。然而,send_request()/receive_response()
組合無法利用這種最佳化。
my_multicall(Nodes, Module, Function, Args) ->
ReqIds = lists:map(fun (Node) ->
erpc:send_request(Node, Module, Function, Args)
end,
Nodes),
lists:map(fun (ReqId) ->
try
{ok, erpc:receive_response(ReqId, infinity)}
catch
Class:Reason ->
{Class, Reason}
end
end,
ReqIds).
如果 erpc
操作失敗,但不知道該函數是否已/將被應用(即,逾時、連線遺失或不正確的 Nodes
列表),則呼叫者不會收到關於已應用函數完成時的結果的任何進一步資訊。如果已應用函數與呼叫程序進行通訊,則此類通訊當然可能會到達呼叫程序。
注意
您不能對執行
apply()
的進程做*任何*假設。它可能是呼叫進程本身、伺服器或新產生的進程。
等同於 erpc:multicast(Nodes,erlang,apply,[Fun,[]])
。
如果發生以下情況,multicast/2
會失敗並拋出 {erpc, badarg}
error
例外:
Nodes
不是合適的原子列表。Fun
不是一個零元函數。
-spec multicast(Nodes, Module, Function, Args) -> ok when Nodes :: [node()], Module :: atom(), Function :: atom(), Args :: [term()].
在節點 Nodes
上評估 apply(Module, Function, Args)
。不會將回應傳遞給呼叫程序。multicast()
在發送 cast 請求後立即傳回。除了錯誤的引數之外,任何失敗都會被靜默忽略。
如果發生以下情況,multicast/4
會失敗並拋出 {erpc, badarg}
error
例外:
Nodes
不是合適的原子列表。請注意,在發生失敗時,某些請求可能已經發送。也就是說,該函數可能在某些節點上應用,也可能沒有。Module
不是一個原子。Function
不是一個原子。Args
不是一個列表。請注意,該列表在客戶端沒有被驗證為正確的列表。
注意
您不能對執行
apply()
的進程做*任何*假設。它可能是伺服器或新產生的進程。
-spec receive_response(RequestId) -> Result when RequestId :: request_id(), Result :: term().
-spec receive_response(RequestId, Timeout) -> Result when RequestId :: request_id(), Timeout :: timeout_time(), Result :: term().
接收對呼叫程序先前使用 send_request/4
發出的 call
請求的回應。
RequestId
應該是先前呼叫 send_request/4
返回的值,並且不應已由 receive_response()
、check_response/4
或 wait_response/4
接收並完整處理對應的回應。
Timeout
設定等待回應的最長時限。如果操作逾時,則會放棄由 RequestId
識別的請求,然後會拋出 {erpc, timeout}
error
例外。也就是說,在逾時後,永遠不會收到對應該請求的回應。如果收到回應,則 call
操作完成,且會返回結果或拋出例外。可能拋出的例外對應於 call/5
可能拋出的相同例外。receive_response/2
在偵測到無效的 RequestId
或傳遞無效的 Timeout
時,會失敗並拋出 {erpc, badarg}
例外。
如果忽略效能,則以下呼叫函式 my_call(Node, Module, Function, Args, Timeout)
等同於呼叫 erpc:call(Node, Module, Function, Args, Timeout)
。call()
可以利用選擇性接收最佳化,從而無需從頭開始掃描訊息佇列以尋找匹配的訊息。然而,send_request()/receive_response()
組合無法利用這種最佳化。
my_call(Node, Module, Function, Args, Timeout) ->
RequestId = erpc:send_request(Node, Module, Function, Args),
erpc:receive_response(RequestId, Timeout).
如果 erpc
操作失敗,但不知道該函數是否已/將被應用(即,逾時或連線遺失),則呼叫者不會收到關於已應用函數完成時的結果的任何進一步資訊。如果已應用函數明確與呼叫程序進行通訊,則此類通訊當然可能會到達呼叫程序。
-spec receive_response(RequestIdCollection, Timeout, Delete) -> {Result, Label, NewRequestIdCollection} | no_request when RequestIdCollection :: request_id_collection(), Timeout :: timeout_time(), Delete :: boolean(), Result :: term(), Label :: term(), NewRequestIdCollection :: request_id_collection().
接收對應於儲存在 RequestIdCollection
中的請求識別碼的 call
請求的回應。RequestIdCollection
的所有請求識別碼都必須對應於使用 send_request/4
或 send_request/6
發出的請求,且所有請求都必須由呼叫此函數的程序發出。
Label
是與回應對應的請求的請求識別碼關聯的標籤。當在 請求識別碼集合中 加入請求識別碼時,或使用 send_request/6
發送請求時,請求識別碼會與標籤關聯。
與 receive_response/2
相比,與特定請求識別碼關聯的返回結果或與特定請求識別碼關聯的例外將會包裝在 3 元組中。此元組的第一個元素等於 receive_response/2
會產生的值,第二個元素等於與特定請求識別碼關聯的 Label
,第三個元素 NewRequestIdCollection
是可能經過修改的請求識別碼集合。error
例外 {erpc, badarg}
和 {erpc, timeout}
不與任何特定請求識別碼關聯,因此不會包裝。
如果 RequestIdCollection
為空,則會返回原子 no_request
。
如果操作逾時,則會放棄由 RequestIdCollection
識別的所有請求,然後會拋出 {erpc, timeout}
error
例外。也就是說,在逾時後,永遠不會收到對應 RequestIdCollection
中任何請求識別碼的回應。receive_response/3
和 wait_response/3
之間的差異在於,receive_response/3
會在逾時時放棄請求,因此會忽略任何潛在的未來回應,而 wait_response/3
則不會。
如果 Delete
等於 true
,則在結果 NewRequestIdCollection
中,與 Label
的關聯將會從 RequestIdCollection
中刪除。如果 Delete
等於 false
,則 NewRequestIdCollection
將等於 RequestIdCollection
。請注意,刪除關聯不是免費的,而且包含已處理請求的集合仍然可以由後續呼叫 receive_response/3
、check_response/3
和 wait_response/3
使用。然而,如果沒有刪除已處理的關聯,則上述呼叫將無法偵測到何時沒有更多未完成的請求要處理,因此您必須以其他方式追蹤此情況,而不是依賴 no_request
返回。請注意,如果您將只包含已處理或已放棄請求的關聯的集合傳遞給 receive_response/3
,則它將始終封鎖,直到觸發由 Timeout
確定的逾時。
請注意,回應可能會在 {erpc, badarg}
例外發生時被消耗,如果是這樣,則將永遠遺失。
-spec reqids_add(RequestId :: request_id(), Label :: term(), RequestIdCollection :: request_id_collection()) -> NewRequestIdCollection :: request_id_collection().
儲存 RequestId
並將 Label
與請求識別碼相關聯,方法是將此資訊新增至 RequestIdCollection
並傳回產生的請求識別碼集合。
-spec reqids_new() -> NewRequestIdCollection :: request_id_collection().
傳回新的空請求識別碼集合。可以使用請求識別碼集合來處理多個未完成的請求。
使用 reqids_add/3
可以將由 send_request/4
發出的請求的請求識別碼儲存在請求識別碼集合中。此類請求識別碼集合稍後可用於通過將集合作為引數傳遞給 check_response/3
、receive_response/3
和 wait_response/3
,來獲取集合中對應請求的一個回應。
可以使用 reqids_size/1
來確定請求識別碼集合中的請求識別碼數量。
-spec reqids_size(RequestIdCollection :: request_id_collection()) -> non_neg_integer().
傳回儲存在 RequestIdCollection
中的請求識別碼數量。
-spec reqids_to_list(RequestIdCollection :: request_id_collection()) -> [{RequestId :: request_id(), Label :: term()}].
傳回一個 {RequestId, Label}
元組列表,該列表對應於 RequestIdCollection
集合中存在的所有帶有相關聯標籤的請求識別碼。
-spec send_request(Node, Fun) -> RequestId when Node :: node(), Fun :: function(), RequestId :: request_id().
等同於 erpc:send_request(Node, erlang, apply, [Fun, []])
。
如果發生以下情況,會失敗並拋出 {erpc, badarg}
error
例外:
Node
不是一個原子。Fun
不是零元函數。
注意
您不能對執行
apply()
的進程做*任何*假設。它可能是伺服器或新產生的進程。
-spec send_request(Node, Module, Function, Args) -> RequestId when Node :: node(), Module :: atom(), Function :: atom(), Args :: [term()], RequestId :: request_id(); (Node, Fun, Label, RequestIdCollection) -> NewRequestIdCollection when Node :: node(), Fun :: function(), Label :: term(), RequestIdCollection :: request_id_collection(), NewRequestIdCollection :: request_id_collection().
將非同步 call
請求發送至節點 Node
。
send_request/4
返回一個請求識別碼,該識別碼稍後會傳遞給 receive_response/2
、wait_response/2
或 check_response/2
,以獲取呼叫請求的回應。除了將請求識別碼直接傳遞給這些函式外,它也可以使用 reqids_add/3
新增到請求識別碼集合中。此類請求識別碼集合稍後可用於通過將集合作為引數傳遞給 receive_response/3
、wait_response/3
或 check_response/3
,來獲取集合中對應請求的一個回應。如果您將要把請求識別碼儲存在請求識別碼集合中,則可能需要考慮改用 send_request/6
。
如果忽略效能,則以下呼叫函式 my_call(Node, Module, Function, Args, Timeout)
等同於呼叫 erpc:call(Node, Module, Function, Args, Timeout)
。call()
可以利用選擇性接收最佳化,從而無需從頭開始掃描訊息佇列以尋找匹配的訊息。然而,send_request()/receive_response()
組合無法利用這種最佳化。
my_call(Node, Module, Function, Args, Timeout) ->
RequestId = erpc:send_request(Node, Module, Function, Args),
erpc:receive_response(RequestId, Timeout).
如果發生以下情況,會失敗並拋出 {erpc, badarg}
error
例外:
Node
不是一個原子。Module
不是一個原子。Function
不是一個原子。Args
不是一個列表。請注意,該列表在客戶端沒有被驗證為正確的列表。
注意
您不能對執行
apply()
的進程做*任何*假設。它可能是伺服器或新產生的進程。
等同於 erpc:send_request(Node, erlang, apply, [Fun,[]]), Label, RequestIdCollection)
。
如果發生以下情況,會失敗並拋出 {erpc, badarg}
error
例外:
Node
不是一個原子。Fun
不是零元函數。- 偵測到
RequestIdCollection
不是請求識別碼集合。
注意
您不能對執行
apply()
的進程做*任何*假設。它可能是伺服器或新產生的進程。
-spec send_request(Node, Module, Function, Args, Label, RequestIdCollection) -> NewRequestIdCollection when Node :: node(), Module :: atom(), Function :: atom(), Args :: [term()], Label :: term(), RequestIdCollection :: request_id_collection(), NewRequestIdCollection :: request_id_collection().
將非同步 call
請求發送至節點 Node
。Label
將與操作的請求識別碼相關聯,並新增至傳回的請求識別碼集合 NewRequestIdCollection
。稍後可以使用該集合,方法是將該集合作為引數傳遞給 receive_response/3
、wait_response/3
或 check_response/3
,從而取得與集合中請求對應的一個回應。
等同於 erpc:reqids_add
(erpc:send_request
(Node, Module, Function, Args), Label, RequestIdCollection)
,但呼叫 send_request/6
效率會稍微高一些。
如果發生以下情況,會失敗並拋出 {erpc, badarg}
error
例外:
Node
不是一個原子。Module
不是一個原子。Function
不是一個原子。Args
不是一個列表。請注意,該列表在客戶端沒有被驗證為正確的列表。- 偵測到
RequestIdCollection
不是請求識別碼集合。
注意
您不能對執行
apply()
的進程做*任何*假設。它可能是伺服器或新產生的進程。
-spec wait_response(RequestId) -> {response, Result} | no_response when RequestId :: request_id(), Result :: term().
等同於 erpc:wait_response(RequestId, 0)
。也就是說,輪詢呼叫程序先前發出的 call
請求的回應訊息。
-spec wait_response(RequestId, WaitTime) -> {response, Result} | no_response when RequestId :: request_id(), WaitTime :: timeout_time(), Result :: term().
等待或輪詢呼叫程序先前使用 send_request/4
發出的 call
請求的回應訊息。
RequestId
應該是先前呼叫 send_request()
返回的值,且對應的回應不應該已經被 check_response/2
、receive_response/2
或 wait_response()
接收並處理完成。
WaitTime
設定等待回應的最長時限。如果在 WaitTime
超時觸發前沒有收到任何回應,則會返回原子 no_response
。在收到回應並由 check_response()
、receive_response()
或 wait_response()
完成處理之前,可以根據需要繼續等待回應多次。如果收到回應,則 call
操作完成,且返回結果為 {response, Result}
,其中 Result
對應於所應用函數返回的值,或者會引發例外。可以引發的例外對應於 call/4
可以引發的相同例外。也就是說,不會引發 {erpc, timeout}
error
例外。如果偵測到無效的 RequestId
或傳遞了無效的 WaitTime
,wait_response/2
將會失敗並引發 {erpc, badarg}
例外。
如果 erpc
操作失敗,但不知道該函數是否已經/將會被應用(也就是說,等待時間值過大,或連接中斷),則呼叫方將不會收到關於所應用函數何時完成的進一步資訊。如果所應用的函數顯式地與呼叫程序通信,則此類通信當然可能會到達呼叫程序。
-spec wait_response(RequestIdCollection, WaitTime, Delete) -> {{response, Result}, Label, NewRequestIdCollection} | no_response | no_request when RequestIdCollection :: request_id_collection(), WaitTime :: timeout_time(), Delete :: boolean(), Label :: term(), NewRequestIdCollection :: request_id_collection(), Result :: term().
等待或輪詢對應於儲存在 RequestIdCollection
中的請求識別碼的 call
請求的回應。RequestIdCollection
的所有請求識別碼都必須對應於使用 send_request/4
或 send_request/6
發出的請求,且所有請求都必須由呼叫此函數的程序發出。
Label
是與回應對應的請求的請求識別碼關聯的標籤。當在 請求識別碼集合中 加入請求識別碼時,或使用 send_request/6
發送請求時,請求識別碼會與標籤關聯。
與 wait_response/2
相比,與特定請求標識符相關的返回結果或與特定請求標識符相關的例外將會被封裝在一個 3 元組中。此元組的第一個元素等於 wait_response/2
將會產生的值,第二個元素等於與特定請求標識符相關的 Label
,第三個元素 NewRequestIdCollection
是一個可能被修改過的請求標識符集合。error
例外 {erpc, badarg}
不與任何特定請求標識符相關聯,因此不會被封裝。
如果 RequestIdCollection
為空,則會返回 no_request
。如果在 WaitTime
超時觸發前沒有收到任何回應,則會返回原子 no_response
。在收到回應並由 check_response()
、receive_response()
或 wait_response()
完成處理之前,可以根據需要繼續等待回應多次。receive_response/3
和 wait_response/3
之間的區別在於,receive_response/3
會在超時時放棄請求,以便忽略任何潛在的未來回應,而 wait_response/3
則不會。
如果 Delete
等於 true
,則與 Label
的關聯將會從結果 NewRequestIdCollection
中的 RequestIdCollection
刪除。如果 Delete
等於 false
,則 NewRequestIdCollection
將會等於 RequestIdCollection
。請注意,刪除關聯並非沒有代價,且包含已處理請求的集合仍然可以被後續呼叫 wait_response/3
、check_response/3
和 receive_response/3
使用。但是,如果沒有刪除已處理的關聯,則上述呼叫將無法偵測到何時沒有更多待處理的請求要處理,因此您必須以其他方式追蹤此資訊,而不是依賴 no_request
返回值。請注意,如果您將一個僅包含已處理或已放棄請求的關聯集合傳遞給 wait_response/3
,它將始終阻塞,直到觸發由 WaitTime
確定的超時,然後返回 no_response
。
請注意,回應可能會在 {erpc, badarg}
例外發生時被消耗,如果是這樣,則將永遠遺失。