Elixir 1.7

Registry




elixir

Registry

एक स्थानीय, विकेंद्रीकृत और स्केलेबल कुंजी-मूल्य प्रक्रिया भंडारण।

यह डेवलपर्स को किसी दिए गए कुंजी के साथ एक या अधिक प्रक्रियाओं को देखने की अनुमति देता है। यदि रजिस्ट्री में है :unique कुंजी, 0 या 1 प्रक्रियाओं के लिए एक प्रमुख बिंदु। यदि रजिस्ट्री अनुमति देती है :duplicate कुंजियाँ, एक एकल कुंजी किसी भी प्रक्रिया को इंगित कर सकती है। दोनों मामलों में, अलग-अलग कुंजी एक ही प्रक्रिया की पहचान कर सकती हैं।

रजिस्ट्री में प्रत्येक प्रविष्टि उस प्रक्रिया से जुड़ी है जिसने कुंजी पंजीकृत की है। यदि प्रक्रिया क्रैश हो जाती है, तो उस प्रक्रिया से संबंधित कुंजी स्वचालित रूप से हटा दी जाती है। रजिस्ट्री में सभी प्रमुख तुलनाएं मैच ऑपरेशन ( ===/2 ) का उपयोग करके की जाती हैं।

रजिस्ट्री का उपयोग विभिन्न प्रयोजनों के लिए किया जा सकता है, जैसे कि नाम लुकअप (उपयोग के :via विकल्प के :via ), भंडारण गुण, कस्टम प्रेषण नियम या एक पबसब कार्यान्वयन। हम नीचे उन उपयोग के कुछ मामलों का पता लगाते हैं।

रजिस्ट्री को पारदर्शी रूप से विभाजित भी किया जा सकता है, जो हजारों या लाखों प्रविष्टियों के साथ अत्यधिक समवर्ती वातावरण पर रजिस्ट्रियों को चलाने के लिए अधिक मापनीय व्यवहार प्रदान करता है।

में उपयोग करना :via

एक बार जब रजिस्ट्री को रजिस्ट्री नाम के साथ Registry.start_link/1 नाम से शुरू किया जाता है, तो इसे {:via, Registry, {registry, key}} tuple: का उपयोग करके नामित प्रक्रियाओं को पंजीकृत और एक्सेस करने के लिए उपयोग किया जा सकता है।

{:ok, _} = Registry.start_link(keys: :unique, name: Registry.ViaTest)
name = {:via, Registry, {Registry.ViaTest, "agent"}}
{:ok, _} = Agent.start_link(fn -> 0 end, name: name)
Agent.get(name, & &1)
#=> 0
Agent.update(name, & &1 + 1)
Agent.get(name, & &1)
#=> 1

आमतौर पर रजिस्ट्री को पर्यवेक्षण के पेड़ के हिस्से के रूप में शुरू किया जाता है, हालांकि:

{Registry, keys: :unique, name: Registry.ViaTest}

केवल अद्वितीय कुंजियों वाली रजिस्ट्रियों का उपयोग इसके :via किया जा सकता है। यदि नाम पहले से ही लिया गया है, तो मामला-विशिष्ट start_link फ़ंक्शन (उपरोक्त उदाहरण में Agent.start_link/2 ) {:error, {:already_started, current_pid}} वापस आ जाएगा।

डिस्पैचर के रूप में उपयोग करना

Registry में एक प्रेषण तंत्र है जो डेवलपर्स को कॉलर से ट्रिगर किए गए कस्टम प्रेषण तर्क को लागू करने की अनुमति देता है। उदाहरण के लिए, मान लें कि हमारे पास एक डुप्लिकेट रजिस्ट्री शुरू हुई है:

{:ok, _} = Registry.start_link(keys: :duplicate, name: Registry.DispatcherTest)

register/3 कॉल करके, विभिन्न प्रक्रियाएं किसी दिए गए कुंजी के तहत पंजीकरण कर सकती हैं और उस कुंजी के तहत किसी भी मूल्य को जोड़ सकती हैं। इस मामले में, चलो "hello" कुंजी के तहत वर्तमान प्रक्रिया को पंजीकृत करते हैं और {IO, :inspect} को संलग्न करते हैं:

{:ok, _} = Registry.register(Registry.DispatcherTest, "hello", {IO, :inspect})

अब, एक दिए गए कुंजी के लिए घटनाओं को भेजने में रुचि रखने वाली इकाई dispatch/3 कुंजी और एक कॉलबैक में कॉल कर सकती है। यह कॉलबैक अनुरोधित कुंजी के तहत पंजीकृत सभी मूल्यों की एक सूची के साथ मंगाया जाएगा, प्रक्रिया के पीआईडी ​​के साथ, जो प्रत्येक मूल्य को पंजीकृत करता है, {pid, value} tuples के रूप में। हमारे उदाहरण में, value ऊपर दिए गए कोड में {module, function} टपल होगा:

Registry.dispatch(Registry.DispatcherTest, "hello", fn entries ->
  for {pid, {module, function}} <- entries, do: apply(module, function, [pid])
end)
# Prints #PID<...> where the pid is for the process that called register/3 above
#=> :ok

डिस्पैचिंग उस प्रक्रिया में होती है जो dispatch/3 या तो क्रमिक रूप से या समवर्ती रूप से कई विभाजनों (स्पॉन्ड कार्यों के माध्यम से) के मामले में कहती है। पंजीकृत प्रक्रियाएं प्रेषण में शामिल नहीं होती हैं जब तक कि उन्हें शामिल करना स्पष्ट रूप से नहीं किया जाता है (उदाहरण के लिए, उन्हें कॉलबैक में संदेश भेजकर)।

इसके अलावा, अगर डिस्पैच करते समय कोई विफलता होती है, तो एक खराब पंजीकरण के कारण, डिस्पैचिंग हमेशा विफल हो जाएगी और पंजीकृत प्रक्रिया को अधिसूचित नहीं किया जाएगा। इसलिए आइए सुनिश्चित करें कि हम कम से कम लपेटें और उन त्रुटियों की रिपोर्ट करें:

require Logger
Registry.dispatch(Registry.DispatcherTest, "hello", fn entries ->
  for {pid, {module, function}} <- entries do
    try do
      apply(module, function, [pid])
    catch
      kind, reason ->
        formatted = Exception.format(kind, reason, __STACKTRACE__)
        Logger.error "Registry.dispatch/3 failed with #{formatted}"
    end
  end
end)
# Prints #PID<...>
#=> :ok

आप स्पष्ट रूप से संदेश भेजकर संपूर्ण apply प्रणाली को भी बदल सकते हैं। इसका उदाहरण हम आगे देखेंगे।

एक पबसब के रूप में उपयोग करना

रजिस्ट्रियों का उपयोग एक स्थानीय, गैर-वितरित, स्केलेबल PubSub को dispatch/3 फ़ंक्शन पर निर्भर करके, समान रूप से पिछले अनुभाग में लागू करने के लिए किया जा सकता है: इस मामले में, हालांकि, हम प्रत्येक संबंधित प्रक्रिया को संदेश भेजेंगे, बजाय एक मॉड्यूल-फ़ंक्शन दिया।

इस उदाहरण में, हम ऑनलाइन विभाजनकर्ताओं की संख्या के लिए विभाजन की संख्या भी निर्धारित करेंगे, जो रजिस्ट्री को अत्यधिक समवर्ती वातावरण पर अधिक प्रदर्शन करेंगे:

{:ok, _} = Registry.start_link(keys: :duplicate, name: Registry.PubSubTest,
                               partitions: System.schedulers_online)
{:ok, _} = Registry.register(Registry.PubSubTest, "hello", [])
Registry.dispatch(Registry.PubSubTest, "hello", fn entries ->
  for {pid, _} <- entries, do: send(pid, {:broadcast, "world"})
end)
#=> :ok

उपरोक्त उदाहरण ने "विषय" (या "कुंजी" के तहत पंजीकृत सभी प्रक्रियाओं के संदेश {:broadcast, "world"} को {:broadcast, "world"} जैसा कि हमने अब तक इसे "hello"

register/3 को दिया गया तीसरा तर्क वर्तमान प्रक्रिया से जुड़ा एक मूल्य है। पिछले खंड में रहते हुए हमने इसे डिस्पैच करते समय उपयोग किया था, इस विशेष उदाहरण में हमें इसमें कोई दिलचस्पी नहीं है, इसलिए हमने इसे एक खाली सूची में सेट किया है। यदि आवश्यक हो तो आप अधिक सार्थक मूल्य संग्रहित कर सकते हैं।

पंजीकरण

विलंबित वितरण को देखते हुए, भेजना और पंजीकरण करना कुशल और तत्काल है। उदाहरण के लिए, यदि कोई प्रक्रिया क्रैश हो जाती है, तो इसकी कुंजियाँ स्वचालित रूप से रजिस्ट्री से हटा दी जाती हैं, लेकिन परिवर्तन तुरंत प्रचारित नहीं हो सकता है। इसका मतलब यह है कि कुछ ऑपरेशंस उन प्रक्रियाओं को वापस कर सकते हैं जो पहले से ही मृत हैं। जब ऐसा हो सकता है, तो यह फ़ंक्शन प्रलेखन में स्पष्ट रूप से कहा जाएगा।

हालाँकि, ध्यान रखें कि वे मामले आमतौर पर एक मुद्दा नहीं होते हैं। आखिरकार, एक पीड द्वारा संदर्भित प्रक्रिया किसी भी समय क्रैश हो सकती है, जिसमें रजिस्ट्री से मूल्य प्राप्त करना और उसे संदेश भेजना शामिल है। मानक पुस्तकालय के कई हिस्सों को उस के साथ सामना करने के लिए डिज़ाइन किया गया है, जैसे कि Process.monitor/1 जो वितरित करेगा :DOWN निगरानी प्रक्रिया पहले से ही मृत हो जाने पर तुरंत संदेश डाउनलोड करें और Kernel.send/2 जो मृतकों के लिए नो-ऑप के रूप में कार्य करता है। प्रक्रियाओं।

ईटीएस

ध्यान दें कि रजिस्ट्री प्रति विभाजन एक ETS तालिका और दो ETS तालिकाओं का उपयोग करती है।

सारांश

प्रकार

guard()

रजिस्ट्री में वस्तुओं पर मिलान करते समय एक गार्ड का मूल्यांकन किया जाना है

guards()

रजिस्ट्री में वस्तुओं पर मिलान करते समय गार्ड की सूची का मूल्यांकन किया जाना है

key()

पंजीकरण पर अनुमत कुंजियों का प्रकार

keys()

रजिस्ट्री का प्रकार

match_pattern()

एक रजिस्ट्री में वस्तुओं पर मिलान करने के लिए एक पैटर्न

meta_key()

रजिस्ट्री मेटाडेटा कुंजियों का प्रकार

meta_value()

रजिस्ट्री मेटाडेटा मानों का प्रकार

registry()

रजिस्ट्री पहचानकर्ता

value()

पंजीकरण पर अनुमत मूल्यों का प्रकार

कार्य

child_spec(opts)

पर्यवेक्षक के तहत एक रजिस्ट्री शुरू करने के लिए एक विनिर्देश देता है

count(registry)

एक रजिस्ट्री में पंजीकृत कुंजी की संख्या देता है। यह निरंतर समय में चलता है

count_match (रजिस्ट्री, कुंजी, पैटर्न, गार्ड \\ [])

pattern मेल खाने वाली registry में दिए गए key तहत {pid, value} जोड़े की संख्या देता है

प्रेषण (रजिस्ट्री, कुंजी, mfa_or_fun, opts \\ [])

दिए गए registry लिए प्रत्येक विभाजन में key तहत सभी प्रविष्टियों के साथ कॉलबैक आमंत्रित करता है

कुंजियाँ (रजिस्ट्री, पीआईडी)

किसी विशेष क्रम में registry में दिए गए pid लिए ज्ञात कुंजी लौटाता है

लुकअप (रजिस्ट्री, कुंजी)

कोई विशेष क्रम में registry में दी गई key लिए {pid, value} जोड़ी को ढूँढता है

मैच (रजिस्ट्री, कुंजी, पैटर्न, गार्ड \\ [])

रिटर्न {pid, value} जोड़े registry में दिए गए key तहत जो pattern मेल खाते हैं

मेटा (रजिस्ट्री, कुंजी)

start_link/3 पर दी गई रजिस्ट्री मेटाडेटा को पढ़ता है

put_meta (रजिस्ट्री, कुंजी, मूल्य)

दुकानों की रजिस्ट्री मेटाडेटा

register/3

registry में दी गई key तहत वर्तमान प्रक्रिया को पंजीकृत करता है

start_link(options)

एक पर्यवेक्षक प्रक्रिया के रूप में रजिस्ट्री शुरू करता है

अपंजीकृत (रजिस्ट्री, कुंजी)

registry में वर्तमान प्रक्रिया से जुड़ी दी गई key लिए सभी प्रविष्टियां अनरजिस्टर्ड करती हैं

unregister_match (रजिस्ट्री, कुंजी, पैटर्न, गार्ड \\ [])

किसी दिए गए कुंजी के पैटर्न के लिए अपंजीकृत प्रविष्टियाँ

update_value (रजिस्ट्री, कुंजी, कॉलबैक)

अद्वितीय registry में वर्तमान प्रक्रिया के लिए key लिए मूल्य अद्यतन करता है

प्रकार

रक्षक()

guard() :: {atom() | term()}

रजिस्ट्री में वस्तुओं पर मिलान करते समय एक गार्ड का मूल्यांकन किया जाना है

गार्ड ()

guards() :: [guard()] | []

रजिस्ट्री में वस्तुओं पर मिलान करते समय गार्ड की सूची का मूल्यांकन किया जाना है

कुंजी ()

key() :: term()

पंजीकरण पर अनुमत कुंजियों का प्रकार

चांबियाँ()

keys() :: :unique | :duplicate

रजिस्ट्री का प्रकार

match_pattern ()

match_pattern() :: atom() | term()

एक रजिस्ट्री में वस्तुओं पर मिलान करने के लिए एक पैटर्न

meta_key ()

meta_key() :: atom() | tuple()

रजिस्ट्री मेटाडेटा कुंजियों का प्रकार

meta_value ()

meta_value() :: term()

रजिस्ट्री मेटाडेटा मानों का प्रकार

रजिस्ट्री ()

registry() :: atom()

रजिस्ट्री पहचानकर्ता

मूल्य ()

value() :: term()

पंजीकरण पर अनुमत मूल्यों का प्रकार

कार्य

child_spec (opts) (1.5.0 से)

पर्यवेक्षक के तहत एक रजिस्ट्री शुरू करने के लिए एक विनिर्देश देता है।

Supervisor देखें।

गणना (रजिस्ट्री) (1.7.0 के बाद से)

count(registry()) :: non_neg_integer()

एक रजिस्ट्री में पंजीकृत कुंजी की संख्या देता है। यह निरंतर समय में चलता है।

उदाहरण

नीचे दिए गए उदाहरण में हम वर्तमान प्रक्रिया को पंजीकृत करते हैं और रजिस्ट्री में कुंजियों की संख्या पूछते हैं:

iex> Registry.start_link(keys: :unique, name: Registry.UniqueCountTest)
iex> Registry.count(Registry.UniqueCountTest)
0
iex> {:ok, _} = Registry.register(Registry.UniqueCountTest, "hello", :world)
iex> {:ok, _} = Registry.register(Registry.UniqueCountTest, "world", :world)
iex> Registry.count(Registry.UniqueCountTest)
2

यही बात डुप्लिकेट रजिस्ट्रियों पर लागू होती है:

iex> Registry.start_link(keys: :duplicate, name: Registry.DuplicateCountTest)
iex> Registry.count(Registry.DuplicateCountTest)
0
iex> {:ok, _} = Registry.register(Registry.DuplicateCountTest, "hello", :world)
iex> {:ok, _} = Registry.register(Registry.DuplicateCountTest, "hello", :world)
iex> Registry.count(Registry.DuplicateCountTest)
2

count_match (रजिस्ट्री, कुंजी, पैटर्न, गार्ड \\ []) (1.7.0 के बाद से)

count_match(registry(), key(), match_pattern(), guards()) :: non_neg_integer()

pattern मेल खाने वाली registry में दिए गए key तहत {pid, value} जोड़े की संख्या देता है।

पैटर्न एक परमाणु या एक टपल होना चाहिए जो रजिस्ट्री में संग्रहीत मूल्य की संरचना से मेल खाएगा। परमाणु :_ का उपयोग किसी दिए गए मान या टुपल तत्व को अनदेखा करने के लिए किया जा सकता है, जबकि परमाणु :"$1" का उपयोग बाद की तुलना के लिए एक चर के लिए अस्थायी रूप से पैटर्न के हिस्से को असाइन करने के लिए किया जा सकता है।

वैकल्पिक रूप से, अधिक सटीक मिलान के लिए गार्ड की शर्तों की एक सूची पारित करना संभव है। प्रत्येक गार्ड एक टपल है, जो चेक का वर्णन करता है जिसे पैटर्न के निर्दिष्ट भाग द्वारा पारित किया जाना चाहिए। उदाहरण के लिए $1 > 1 गार्ड की स्थिति को {:>, :"$1", 1} टुपल के रूप में व्यक्त किया जाएगा। कृपया ध्यान दें कि गार्ड की स्थिति केवल निर्दिष्ट चर के लिए काम करेगी जैसे :"$1" , :"$2" , आदि विशेष मैच चर के उपयोग से बचें :"$_" और :"$$" , क्योंकि यह अपेक्षित रूप से काम नहीं कर सकता है।

मैच नहीं होने पर जीरो वापस कर दिया जाएगा।

अद्वितीय रजिस्ट्रियों के लिए, एक एकल विभाजन लुकअप आवश्यक है। डुप्लिकेट रजिस्ट्रियों के लिए, सभी विभाजनों को देखना होगा।

उदाहरण

नीचे दिए गए उदाहरण में हम एक डुप्लिकेट रजिस्ट्री में एक ही कुंजी के तहत वर्तमान प्रक्रिया को पंजीकृत करते हैं लेकिन विभिन्न मूल्यों के साथ:

iex> Registry.start_link(keys: :duplicate, name: Registry.MatchTest)
iex> {:ok, _} = Registry.register(Registry.MatchTest, "hello", {1, :atom, 1})
iex> {:ok, _} = Registry.register(Registry.MatchTest, "hello", {2, :atom, 2})
iex> Registry.count_match(Registry.MatchTest, "hello", {1, :_, :_})
1
iex> Registry.count_match(Registry.MatchTest, "hello", {2, :_, :_})
1
iex> Registry.count_match(Registry.MatchTest, "hello", {:_, :atom, :_})
2
iex> Registry.count_match(Registry.MatchTest, "hello", {:"$1", :_, :"$1"})
2
iex> Registry.count_match(Registry.MatchTest, "hello", {:_, :_, :"$1"}, [{:>, :"$1", 1}])
1
iex> Registry.count_match(Registry.MatchTest, "hello", {:_, :"$1", :_}, [{:is_atom, :"$1"}])
2

प्रेषण (रजिस्ट्री, कुंजी, mfa_or_fun, opts \\ []) (1.4.0 से)

dispatch(registry(), key(), dispatcher, keyword()) :: :ok
when dispatcher:
       (entries :: [{pid(), value()}] -> term()) | {module(), atom(), [any()]}

दिए गए registry लिए प्रत्येक विभाजन में key तहत सभी प्रविष्टियों के साथ कॉलबैक आमंत्रित करता है।

entries की सूची दो-तत्व ट्यूपलों की एक गैर-रिक्त सूची है जहां पहला तत्व पीआईडी ​​है और दूसरा तत्व पीआईडी ​​से जुड़ा मूल्य है। यदि दी गई कुंजी के लिए कोई प्रविष्टि नहीं है, तो कॉलबैक को कभी भी लागू नहीं किया जाएगा।

यदि रजिस्ट्री का विभाजन किया जाता है, तो कॉलबैक प्रति विभाजन कई बार लागू किया जाता है। यदि रजिस्ट्री का विभाजन और parallel: true को एक विकल्प के रूप में दिया जाता है, तो प्रेषण समानांतर में होता है। दोनों मामलों में, कॉलबैक केवल तब ही लागू किया जाता है जब उस विभाजन के लिए प्रविष्टियाँ हों।

कस्टम प्रेषण या एक पबसब प्रणाली के निर्माण के लिए dispatch/3 फ़ंक्शन का उपयोग करने के उदाहरणों के लिए मॉड्यूल प्रलेखन देखें।

कुंजियाँ (रजिस्ट्री, पीआईडी) (1.4.0 से)

keys(registry(), pid()) :: [key()]

किसी विशेष क्रम में registry में दिए गए pid लिए ज्ञात कुंजी लौटाता है।

यदि रजिस्ट्री अद्वितीय है, तो कुंजियाँ अद्वितीय हैं। अन्यथा वे डुप्लिकेट हो सकते हैं यदि प्रक्रिया कई बार एक ही कुंजी के तहत पंजीकृत थी। यदि प्रक्रिया मृत है या इस रजिस्ट्री में इसकी कोई कुंजी नहीं है, तो सूची खाली हो जाएगी।

उदाहरण

एक अद्वितीय रजिस्ट्री के तहत पंजीकरण कई प्रविष्टियों की अनुमति नहीं देता है:

iex> Registry.start_link(keys: :unique, name: Registry.UniqueKeysTest)
iex> Registry.keys(Registry.UniqueKeysTest, self())
[]
iex> {:ok, _} = Registry.register(Registry.UniqueKeysTest, "hello", :world)
iex> Registry.register(Registry.UniqueKeysTest, "hello", :later) # registry is :unique
{:error, {:already_registered, self()}}
iex> Registry.keys(Registry.UniqueKeysTest, self())
["hello"]

हालांकि डुप्लिकेट रजिस्ट्रियों के लिए यह संभव है:

iex> Registry.start_link(keys: :duplicate, name: Registry.DuplicateKeysTest)
iex> Registry.keys(Registry.DuplicateKeysTest, self())
[]
iex> {:ok, _} = Registry.register(Registry.DuplicateKeysTest, "hello", :world)
iex> {:ok, _} = Registry.register(Registry.DuplicateKeysTest, "hello", :world)
iex> Registry.keys(Registry.DuplicateKeysTest, self())
["hello", "hello"]

लुकअप (रजिस्ट्री, कुंजी) (1.4.0 से)

lookup(registry(), key()) :: [{pid(), value()}]

कोई विशेष क्रम में registry में दी गई key लिए {pid, value} जोड़ी को ढूँढता है।

मैच न होने पर खाली सूची।

अद्वितीय रजिस्ट्रियों के लिए, एक एकल विभाजन लुकअप आवश्यक है। डुप्लिकेट रजिस्ट्रियों के लिए, सभी विभाजनों को देखना होगा।

उदाहरण

नीचे दिए गए उदाहरण में हम वर्तमान प्रक्रिया को पंजीकृत करते हैं और इसे स्वयं और अन्य प्रक्रियाओं से देखते हैं:

iex> Registry.start_link(keys: :unique, name: Registry.UniqueLookupTest)
iex> Registry.lookup(Registry.UniqueLookupTest, "hello")
[]
iex> {:ok, _} = Registry.register(Registry.UniqueLookupTest, "hello", :world)
iex> Registry.lookup(Registry.UniqueLookupTest, "hello")
[{self(), :world}]
iex> Task.async(fn -> Registry.lookup(Registry.UniqueLookupTest, "hello") end) |> Task.await()
[{self(), :world}]

यही बात डुप्लिकेट रजिस्ट्रियों पर लागू होती है:

iex> Registry.start_link(keys: :duplicate, name: Registry.DuplicateLookupTest)
iex> Registry.lookup(Registry.DuplicateLookupTest, "hello")
[]
iex> {:ok, _} = Registry.register(Registry.DuplicateLookupTest, "hello", :world)
iex> Registry.lookup(Registry.DuplicateLookupTest, "hello")
[{self(), :world}]
iex> {:ok, _} = Registry.register(Registry.DuplicateLookupTest, "hello", :another)
iex> Enum.sort(Registry.lookup(Registry.DuplicateLookupTest, "hello"))
[{self(), :another}, {self(), :world}]

मैच (रजिस्ट्री, कुंजी, पैटर्न, गार्ड \\ []) (1.4.0 के बाद से)

match(registry(), key(), match_pattern(), guards()) :: [{pid(), term()}]

रिटर्न {pid, value} जोड़े registry में दिए गए key तहत जो pattern मेल खाते हैं।

पैटर्न एक परमाणु या एक टपल होना चाहिए जो रजिस्ट्री में संग्रहीत मूल्य की संरचना से मेल खाएगा। परमाणु :_ का उपयोग किसी दिए गए मान या टुपल तत्व को अनदेखा करने के लिए किया जा सकता है, जबकि परमाणु :"$1" का उपयोग बाद की तुलना के लिए एक चर के लिए अस्थायी रूप से पैटर्न के हिस्से को असाइन करने के लिए किया जा सकता है।

वैकल्पिक रूप से, अधिक सटीक मिलान के लिए गार्ड की शर्तों की एक सूची पारित करना संभव है। प्रत्येक गार्ड एक टपल है, जो चेक का वर्णन करता है जिसे पैटर्न के निर्दिष्ट भाग द्वारा पारित किया जाना चाहिए। उदाहरण के लिए $1 > 1 गार्ड की स्थिति को {:>, :"$1", 1} टुपल के रूप में व्यक्त किया जाएगा। कृपया ध्यान दें कि गार्ड की स्थिति केवल निर्दिष्ट चर के लिए काम करेगी जैसे :"$1" , :"$2" , आदि विशेष मैच चर के उपयोग से बचें :"$_" और :"$$" , क्योंकि यह अपेक्षित रूप से काम नहीं कर सकता है।

मिलान न होने पर खाली सूची वापस कर दी जाएगी।

अद्वितीय रजिस्ट्रियों के लिए, एक एकल विभाजन लुकअप आवश्यक है। डुप्लिकेट रजिस्ट्रियों के लिए, सभी विभाजनों को देखना होगा।

उदाहरण

नीचे दिए गए उदाहरण में हम एक डुप्लिकेट रजिस्ट्री में एक ही कुंजी के तहत वर्तमान प्रक्रिया को पंजीकृत करते हैं लेकिन विभिन्न मूल्यों के साथ:

iex> Registry.start_link(keys: :duplicate, name: Registry.MatchTest)
iex> {:ok, _} = Registry.register(Registry.MatchTest, "hello", {1, :atom, 1})
iex> {:ok, _} = Registry.register(Registry.MatchTest, "hello", {2, :atom, 2})
iex> Registry.match(Registry.MatchTest, "hello", {1, :_, :_})
[{self(), {1, :atom, 1}}]
iex> Registry.match(Registry.MatchTest, "hello", {2, :_, :_})
[{self(), {2, :atom, 2}}]
iex> Registry.match(Registry.MatchTest, "hello", {:_, :atom, :_}) |> Enum.sort()
[{self(), {1, :atom, 1}}, {self(), {2, :atom, 2}}]
iex> Registry.match(Registry.MatchTest, "hello", {:"$1", :_, :"$1"}) |> Enum.sort()
[{self(), {1, :atom, 1}}, {self(), {2, :atom, 2}}]
iex> Registry.match(Registry.MatchTest, "hello", {:_, :_, :"$1"}, [{:>, :"$1", 1}])
[{self(), {2, :atom, 2}}]
iex> Registry.match(Registry.MatchTest, "hello", {:_, :"$1", :_}, [{:is_atom, :"$1"}]) |> Enum.sort()
[{self(), {1, :atom, 1}}, {self(), {2, :atom, 2}}]

मेटा (रजिस्ट्री, कुंजी) (1.4.0 से)

meta(registry(), meta_key()) :: {:ok, meta_value()} | :error

start_link/3 पर दी गई रजिस्ट्री मेटाडेटा को पढ़ता है।

कुंजी के रूप में परमाणुओं और टुपल्स की अनुमति है।

उदाहरण

iex> Registry.start_link(keys: :unique, name: Registry.MetaTest, meta: [custom_key: "custom_value"])
iex> Registry.meta(Registry.MetaTest, :custom_key)
{:ok, "custom_value"}
iex> Registry.meta(Registry.MetaTest, :unknown_key)
:error

put_meta (रजिस्ट्री, कुंजी, मूल्य) (1.4.0 से)

put_meta(registry(), meta_key(), meta_value()) :: :ok

दुकानों की रजिस्ट्री मेटाडेटा।

कुंजी के रूप में परमाणुओं और टुपल्स की अनुमति है।

उदाहरण

iex> Registry.start_link(keys: :unique, name: Registry.PutMetaTest)
iex> Registry.put_meta(Registry.PutMetaTest, :custom_key, "custom_value")
:ok
iex> Registry.meta(Registry.PutMetaTest, :custom_key)
{:ok, "custom_value"}
iex> Registry.put_meta(Registry.PutMetaTest, {:tuple, :key}, "tuple_value")
:ok
iex> Registry.meta(Registry.PutMetaTest, {:tuple, :key})
{:ok, "tuple_value"}

रजिस्टर (रजिस्ट्री, कुंजी, मूल्य) (1.4.0 के बाद से)

register(registry(), key(), value()) ::
  {:ok, pid()} | {:error, {:already_registered, pid()}}

registry में दी गई key तहत वर्तमान प्रक्रिया को पंजीकृत करता है।

इस पंजीकरण के साथ जुड़े होने का एक मूल्य भी दिया जाना चाहिए। जब भी डिस्पैच या एक प्रमुख लुकअप किया जाता है, तो यह मान पुनः प्राप्त किया जाएगा।

यह फ़ंक्शन {:ok, owner} या {:error, reason} owner रजिस्ट्री विभाजन में पीआईडी ​​के लिए जिम्मेदार है। मालिक स्वचालित रूप से कॉलर से जुड़ा हुआ है।

यदि रजिस्ट्री में अद्वितीय कुंजियाँ हैं, तो यह {:ok, owner} वापस करेगा जब तक कि कुंजी पहले से ही एक पिड से जुड़ी न हो, जिस स्थिति में यह वापस लौटा है {:error, {:already_registered, pid}}

यदि रजिस्ट्री में डुप्लिकेट कुंजियाँ हैं, तो एक ही कुंजी के तहत वर्तमान प्रक्रिया से कई पंजीकरण की अनुमति है।

उदाहरण

एक अद्वितीय रजिस्ट्री के तहत पंजीकरण कई प्रविष्टियों की अनुमति नहीं देता है:

iex> Registry.start_link(keys: :unique, name: Registry.UniqueRegisterTest)
iex> {:ok, _} = Registry.register(Registry.UniqueRegisterTest, "hello", :world)
iex> Registry.register(Registry.UniqueRegisterTest, "hello", :later)
{:error, {:already_registered, self()}}
iex> Registry.keys(Registry.UniqueRegisterTest, self())
["hello"]

हालांकि डुप्लिकेट रजिस्ट्रियों के लिए यह संभव है:

iex> Registry.start_link(keys: :duplicate, name: Registry.DuplicateRegisterTest)
iex> {:ok, _} = Registry.register(Registry.DuplicateRegisterTest, "hello", :world)
iex> {:ok, _} = Registry.register(Registry.DuplicateRegisterTest, "hello", :world)
iex> Registry.keys(Registry.DuplicateRegisterTest, self())
["hello", "hello"]

start_link (विकल्प) (1.5.0 के बाद से)

start_link(
  keys: keys(),
  name: registry(),
  partitions: pos_integer(),
  listeners: [atom()],
  meta: meta
) :: {:ok, pid()} | {:error, term()}
when meta: [{meta_key(), meta_value()}]

एक पर्यवेक्षक प्रक्रिया के रूप में रजिस्ट्री शुरू करता है।

मैन्युअल रूप से इसे शुरू किया जा सकता है:

Registry.start_link(keys: :unique, name: MyApp.Registry)

आपके पर्यवेक्षक वृक्ष में, आप लिखेंगे:

Supervisor.start_link([
  {Registry, keys: :unique, name: MyApp.Registry}
])

गहन कार्यभार के लिए, रजिस्ट्री का विभाजन भी किया जा सकता है (यह निर्दिष्ट करके :partitions विकल्प)। यदि विभाजन की आवश्यकता होती है, तो एक अच्छा डिफाल्ट उपलब्ध विभाजन की संख्या के लिए विभाजन की संख्या निर्धारित करना है:

Registry.start_link(keys: :unique, name: MyApp.Registry,
                    partitions: System.schedulers_online())

या:

Supervisor.start_link([
  {Registry, keys: :unique, name: MyApp.Registry,
             partitions: System.schedulers_online()}
])

विकल्प

रजिस्ट्री को निम्नलिखित कुंजियों की आवश्यकता होती है:

  • :keys - चुनें अगर चाबियाँ हैं :unique या :duplicate
  • :name - रजिस्ट्री और उसके तालिकाओं का नाम

निम्नलिखित कुंजियाँ वैकल्पिक हैं:

  • :partitions - रजिस्ट्री में विभाजन की संख्या। 1 चूक।
  • :listeners - नामित प्रक्रियाओं की एक सूची जो अधिसूचित की जाती है :register और :unregister घटनाएं। यदि पंजीकृत प्रक्रिया दुर्घटनाग्रस्त हो जाए तो श्रोता द्वारा पंजीकृत प्रक्रिया की निगरानी की जानी चाहिए।
  • :meta - रजिस्ट्री से संलग्न होने के लिए मेटाडेटा की एक कीवर्ड सूची।

अपंजीकृत (रजिस्ट्री, कुंजी) (1.4.0 के बाद से)

unregister(registry(), key()) :: :ok

registry में वर्तमान प्रक्रिया से जुड़ी दी गई key लिए सभी प्रविष्टियां अनरजिस्टर्ड करती हैं।

हमेशा रिटर्न :ok और स्वचालित रूप से मालिक से वर्तमान प्रक्रिया को अनलिंक करता है यदि वर्तमान प्रक्रिया से जुड़ी कोई और कुंजी नहीं है। "स्वामी" के बारे में अधिक पढ़ने के लिए register/3 भी देखें।

उदाहरण

अद्वितीय रजिस्ट्रियों के लिए:

iex> Registry.start_link(keys: :unique, name: Registry.UniqueUnregisterTest)
iex> Registry.register(Registry.UniqueUnregisterTest, "hello", :world)
iex> Registry.keys(Registry.UniqueUnregisterTest, self())
["hello"]
iex> Registry.unregister(Registry.UniqueUnregisterTest, "hello")
:ok
iex> Registry.keys(Registry.UniqueUnregisterTest, self())
[]

डुप्लिकेट रजिस्ट्रियों के लिए:

iex> Registry.start_link(keys: :duplicate, name: Registry.DuplicateUnregisterTest)
iex> Registry.register(Registry.DuplicateUnregisterTest, "hello", :world)
iex> Registry.register(Registry.DuplicateUnregisterTest, "hello", :world)
iex> Registry.keys(Registry.DuplicateUnregisterTest, self())
["hello", "hello"]
iex> Registry.unregister(Registry.DuplicateUnregisterTest, "hello")
:ok
iex> Registry.keys(Registry.DuplicateUnregisterTest, self())
[]

unregister_match (रजिस्ट्री, कुंजी, पैटर्न, गार्ड \\ []) (1.5.0 के बाद से)

किसी दिए गए कुंजी के पैटर्न के लिए अपंजीकृत प्रविष्टियाँ।

उदाहरण

अद्वितीय रजिस्ट्रियों के लिए इसका उपयोग किसी विशेष मूल्य से मेल खाता है या नहीं के आधार पर एक कुंजी को सशर्त रूप से अपंजीकृत करने के लिए किया जा सकता है।

iex> Registry.start_link(keys: :unique, name: Registry.UniqueUnregisterMatchTest)
iex> Registry.register(Registry.UniqueUnregisterMatchTest, "hello", :world)
iex> Registry.keys(Registry.UniqueUnregisterMatchTest, self())
["hello"]
iex> Registry.unregister_match(Registry.UniqueUnregisterMatchTest, "hello", :foo)
:ok
iex> Registry.keys(Registry.UniqueUnregisterMatchTest, self())
["hello"]
iex> Registry.unregister_match(Registry.UniqueUnregisterMatchTest, "hello", :world)
:ok
iex> Registry.keys(Registry.UniqueUnregisterMatchTest, self())
[]

डुप्लिकेट रजिस्ट्रियों के लिए:

iex> Registry.start_link(keys: :duplicate, name: Registry.DuplicateUnregisterMatchTest)
iex> Registry.register(Registry.DuplicateUnregisterMatchTest, "hello", :world_a)
iex> Registry.register(Registry.DuplicateUnregisterMatchTest, "hello", :world_b)
iex> Registry.register(Registry.DuplicateUnregisterMatchTest, "hello", :world_c)
iex> Registry.keys(Registry.DuplicateUnregisterMatchTest, self())
["hello", "hello", "hello"]
iex> Registry.unregister_match(Registry.DuplicateUnregisterMatchTest, "hello", :world_a)
:ok
iex> Registry.keys(Registry.DuplicateUnregisterMatchTest, self())
["hello", "hello"]
iex> Registry.lookup(Registry.DuplicateUnregisterMatchTest, "hello")
[{self(), :world_b}, {self(), :world_c}]

update_value (रजिस्ट्री, कुंजी, कॉलबैक) (1.4.0 के बाद से)

update_value(registry(), key(), (value() -> value())) ::
  {new_value :: term(), old_value :: term()} | :error

अद्वितीय registry में वर्तमान प्रक्रिया के लिए key लिए मूल्य अद्यतन करता है।

एक {new_value, old_value} tuple या :error लौटाता है यदि वर्तमान प्रक्रिया में ऐसी कोई कुंजी नहीं दी गई है।

यदि एक गैर-अद्वितीय रजिस्ट्री दी जाती है, तो एक त्रुटि उठाई जाती है।

उदाहरण

iex> Registry.start_link(keys: :unique, name: Registry.UpdateTest)
iex> {:ok, _} = Registry.register(Registry.UpdateTest, "hello", 1)
iex> Registry.lookup(Registry.UpdateTest, "hello")
[{self(), 1}]
iex> Registry.update_value(Registry.UpdateTest, "hello", &(&1 + 1))
{2, 1}
iex> Registry.lookup(Registry.UpdateTest, "hello")
[{self(), 2}]