Cloister โ†’ ื ื™ื”ื•ืœ ืงืœืกื˜ืจ OTP ืคืฉื•ื˜

ื›ืžืขื˜ ื›ืœ ืืคืœื™ืงืฆื™ื” ืขืกืงื™ืช ืžืฆืœื™ื—ื” ื ื›ื ืกืช ื‘ืžื•ืงื“ื ืื• ื‘ืžืื•ื—ืจ ืœืฉืœื‘ ืฉื‘ื• ื ื“ืจืฉืช ืงื ื” ืžื™ื“ื” ืื•ืคืงื™. ื‘ืžืงืจื™ื ืจื‘ื™ื, ืืชื” ื™ื›ื•ืœ ืคืฉื•ื˜ ืœื”ืชื—ื™ืœ ืžื•ืคืข ื—ื“ืฉ ื•ืœื”ืคื—ื™ืช ืืช ืžืžื•ืฆืข ื”ืขื•ืžืก. ืื‘ืœ ื™ืฉ ื’ื ืžืงืจื™ื ืคื—ื•ืช ื˜ืจื™ื•ื•ื™ืืœื™ื™ื ืฉื‘ื”ื ืื ื—ื ื• ืฆืจื™ื›ื™ื ืœื”ื‘ื˜ื™ื— ืฉืฆืžืชื™ื ืฉื•ื ื™ื ื™ื“ืขื• ื–ื” ืขืœ ื–ื” ื•ืœื—ืœืง ื‘ื–ื”ื™ืจื•ืช ืืช ืขื•ืžืก ื”ืขื‘ื•ื“ื”.

Cloister โ†’ ื ื™ื”ื•ืœ ืงืœืกื˜ืจ OTP ืคืฉื•ื˜

ื–ื” ื™ืฆื ื›ืœ ื›ืš ื‘ืจ ืžื–ืœ ืฉ erlang, ืฉื‘ื—ืจื ื• ื‘ืฉืœ ื”ืชื—ื‘ื™ืจ ื”ื ืขื™ื ื•ื”ื”ื™ื™ืค ืกื‘ื™ื‘ื•, ื™ืฉ ืœื• ืžื“ืจื’ื” ืจืืฉื•ื ื” ืชืžื™ื›ื” ื‘ืžืขืจื›ื•ืช ืžื‘ื•ื–ืจื•ืช. ื‘ืชื™ืื•ืจื™ื”, ื–ื” ื ืฉืžืข ื˜ืจื™ื•ื•ื™ืืœื™ ืœื—ืœื•ื˜ื™ืŸ:

ื”ืขื‘ืจืช ื”ื•ื“ืขื•ืช ื‘ื™ืŸ ืชื”ืœื™ื›ื™ื ื‘ืฆืžืชื™ื ืฉื•ื ื™ื, ื›ืžื• ื’ื ื‘ื™ืŸ ืงื™ืฉื•ืจื™ื ืœืฆื’ื™ื, ื”ื™ื ืฉืงื•ืคื” [โ€ฆ]

ื‘ืคื•ืขืœ, ื”ื›ืœ ืงืฆืช ื™ื•ืชืจ ืžืกื•ื‘ืš. ืžื•ืคืฅ erlang ืคื•ืชื— ื›ืืฉืจ "ืžื™ื›ืœ" ืคื™ืจื•ืฉื• ืงื•ืคืกืช ื‘ืจื–ืœ ื’ื“ื•ืœื” ืœืžืฉืœื•ื—, ื•"ื“ื•ืงืจ" ื”ื™ื” ืคืฉื•ื˜ ืžื™ืœื” ื ืจื“ืคืช ืœ-longshoreman. IN IP4 ื”ื™ื• ื”ืจื‘ื” ื›ืชื•ื‘ื•ืช ืœื ืชืคื•ืกื•ืช, ื”ืคืกืงื•ืช ืจืฉืช ื ื’ืจืžื• ื‘ื“ืจืš ื›ืœืœ ืขืœ ื™ื“ื™ ืขื›ื‘ืจื•ืฉื™ื ืฉืœืขืกื• ื“ืจืš ื”ื›ื‘ืœ, ื•ื–ืžืŸ ื”ืคืขื•ืœื” ื”ืžืžื•ืฆืข ืฉืœ ืžืขืจื›ืช ื”ื™ื™ืฆื•ืจ ื ืžื“ื“ ื‘ืขืฉืจื•ืช ืฉื ื™ื.

ืขื›ืฉื™ื• ื›ื•ืœื ื• ืขืฆืžืื™ื™ื ืœื”ืคืœื™ื, ืืจื•ื–ื™ื ื•ืคื•ืขืœื™ื ืžื‘ื•ื–ืจื™ื erlang ื‘ืกื‘ื™ื‘ื” ืฉื‘ื” ื›ืชื•ื‘ื•ืช IP ื“ื™ื ืžื™ื•ืช ืžื—ื•ืœืงื•ืช ืขืœ ืคื™ ืขืงืจื•ืŸ ื”ืืงืจืื™ื•ืช ื”ื’ื“ื•ืœื”, ื•ืฆืžืชื™ื ื™ื›ื•ืœื™ื ืœื”ื•ืคื™ืข ื•ืœื”ื™ืขืœื ื‘ื’ื—ืžื” ืฉืœ ื”ืขืงื‘ ื”ืฉืžืืœื™ ืฉืœ ื”ืžืชื–ืžืŸ. ื›ื“ื™ ืœืžื ื•ืข ืขืจื™ืžื•ืช ืฉืœ ืงื•ื“ ืœื•ื— ื‘ื›ืœ ืคืจื•ื™ืงื˜ ืฉืžืจื™ืฅ ืงื•ื‘ืฅ ืžื‘ื•ื–ืจ erlang, ื›ื“ื™ ืœื”ื™ืœื—ื ื‘ืกื‘ื™ื‘ื” ื”ืขื•ื™ื ืช, ื ื“ืจืฉืช ืขื–ืจื”.

ืฉื™ื ืœื‘: ืื ื™ ืžื•ื“ืข ืœื›ืš ืฉื™ืฉ libcluster. ื–ื” ืžืžืฉ ืžื’ื ื™ื‘, ื™ืฉ ืœื• ืœืžืขืœื” ืžืืœืฃ ื›ื•ื›ื‘ื™ื, ื”ืกื•ืคืจ ืžืคื•ืจืกื ื‘ืงื”ื™ืœื” ื•ื›ืœ ื–ื”. ืื ื”ืฉื™ื˜ื•ืช ืฉืžืฆื™ืขื” ื—ื‘ื™ืœื” ื–ื• ืœื™ืฆื™ืจื” ื•ืชื—ื–ื•ืงื” ืฉืœ ืืฉื›ื•ืœ ืžืกืคื™ืงื•ืช ืœืš, ืื ื™ ืฉืžื— ื‘ืฉื‘ื™ืœืš. ืœืฆืขืจื™, ืื ื™ ืฆืจื™ืš ื”ืจื‘ื” ื™ื•ืชืจ. ืื ื™ ืจื•ืฆื” ืœืฉืœื•ื˜ ืขืœ ื”ื”ื’ื“ืจื” ืœืคืจื˜ื™ ืคืจื˜ื™ื ื•ืœื ืœื”ื™ื•ืช ืฆื•ืคื” ืžื‘ื—ื•ืฅ ื‘ืชืื˜ืจื•ืŸ ืฉืœ ืืจื’ื•ืŸ ืžื—ื“ืฉ ืฉืœ ืืฉื›ื•ืœ.

ื“ืจื™ืฉื•ืช

ืžื” ืฉื”ื™ื™ืชื™ ืฆืจื™ืš ื‘ืื•ืคืŸ ืื™ืฉื™ ื–ื” ืกืคืจื™ื™ื” ืฉืชืฉืชืœื˜ ืขืœ ื”ื ื™ื”ื•ืœ ืฉืœ ื”ืืฉื›ื•ืœ ื•ืชื”ื™ื” ืœื” ืืช ื”ืžืืคื™ื™ื ื™ื ื”ื‘ืื™ื:

  • ืขื‘ื•ื“ื” ืฉืงื•ืคื” ืขื ืจืฉื™ืžื” ืžืงื•ื“ื“ืช ืฉืœ ืฆืžืชื™ื ื•ื’ื™ืœื•ื™ ื“ื™ื ืžื™ ื‘ืืžืฆืขื•ืช ืฉื™ืจื•ืชื™ื erlang;
  • ื”ืชืงืฉืจื•ืช ื—ื•ื–ืจืช ืคื•ื ืงืฆื™ื•ื ืœื™ืช ืžืœืื” ืขื‘ื•ืจ ื›ืœ ืฉื™ื ื•ื™ ื‘ื˜ื•ืคื•ืœื•ื’ื™ื” (ืฆื•ืžืช ืฉื, ืฆื•ืžืช ื›ืืŸ, ื—ื•ืกืจ ื™ืฆื™ื‘ื•ืช ื‘ืจืฉืช, ืคื™ืฆื•ืœื™ื);
  • ืžืžืฉืง ืฉืงื•ืฃ ืœื”ืคืขืœืช ืืฉื›ื•ืœ ืขื ืฉืžื•ืช ืืจื•ื›ื™ื ื•ืงืฆืจื™ื, ื›ืžื• ืขื :nonode@nohost;
  • ืชืžื™ื›ืช Docker ืžื—ื•ืฅ ืœืงื•ืคืกื”, ืœืœื ืฆื•ืจืš ื‘ื›ืชื™ื‘ืช ืงื•ื“ ืชืฉืชื™ืช.

ื–ื” ื”ืื—ืจื•ืŸ ืื•ืžืจ ืฉืœืื—ืจ ืฉื‘ื“ืงืชื™ ืืช ื”ืืคืœื™ืงืฆื™ื” ื‘ืื•ืคืŸ ืžืงื•ืžื™ ื‘ :nonode@nohost, ืื• ื‘ืกื‘ื™ื‘ื” ื”ืžื•ืคืฆืช ื‘ืื•ืคืŸ ืžืœืื›ื•ืชื™ ื‘ืืžืฆืขื•ืช test_cluster_task, ืื ื™ ืจืง ืจื•ืฆื” ืœืจื•ืฅ docker-compose up --scale my_app=3 ื•ืจืื” ื›ื™ืฆื“ ื”ื•ื ืžื‘ืฆืข ืฉืœื•ืฉื” ืžื•ืคืขื™ื ื‘-docker ืœืœื ืฉื™ื ื•ื™ื™ ืงื•ื“. ืื ื™ ื’ื ืจื•ืฆื” ืืคืœื™ืงืฆื™ื•ืช ืชืœื•ื™ื•ืช ื›ืžื• mnesia - ื›ืืฉืจ ื”ื˜ื•ืคื•ืœื•ื’ื™ื” ืžืฉืชื ื”, ืžืื—ื•ืจื™ ื”ืงืœืขื™ื ื”ื ื‘ื•ื ื™ื ืžื—ื“ืฉ ืืช ื”ืืฉื›ื•ืœ ื‘ืฉื™ื“ื•ืจ ื—ื™ ืœืœื ื‘ืขื™ื˜ื” ื ื•ืกืคืช ืžื”ืืคืœื™ืงืฆื™ื”.

ืงืœื•ืกื˜ืจ ืœื ื ื•ืขื“ ืœื”ื™ื•ืช ืกืคืจื™ื™ื” ื”ืžืกื•ื’ืœืช ืœื”ื›ืœ, ื”ื—ืœ ืžืชืžื™ื›ื” ื‘ืืฉื›ื•ืœ ื•ืขื“ ื”ื›ื ืช ืงืคื”. ื–ื” ืœื ื›ื“ื•ืจ ื›ืกืฃ ืฉืžื˜ืจืชื• ืœื›ืกื•ืช ืืช ื›ืœ ื”ืžืงืจื™ื ื”ืืคืฉืจื™ื™ื, ืื• ืœื”ื™ื•ืช ืคืชืจื•ืŸ ืฉืœื ืžื‘ื—ื™ื ื” ืืงื“ืžื™ืช ื‘ืžื•ื‘ืŸ ืฉืชื™ืื•ืจื˜ื™ืงื ื™ื ืž CS ืœื”ื›ื ื™ืก ืœืงื“ื ืฆื™ื” ื”ื–ื•. ื”ืกืคืจื™ื™ื” ื”ื–ื• ื ื•ืขื“ื” ืœืฉืจืช ืžื˜ืจื” ืžืื•ื“ ื‘ืจื•ืจื”, ืื‘ืœ ืœืขืฉื•ืช ืืช ื”ืขื‘ื•ื“ื” ื”ืœื ื’ื“ื•ืœื” ืฉืœื” ื‘ืฆื•ืจื” ืžื•ืฉืœืžืช. ืžื˜ืจื” ื–ื• ืชื”ื™ื” ืœืกืคืง ืฉืงื™ืคื•ืช ืžืœืื” ื‘ื™ืŸ ืกื‘ื™ื‘ืช ื”ืคื™ืชื•ื— ื”ืžืงื•ืžื™ืช ืœื‘ื™ืŸ ืกื‘ื™ื‘ื” ืืœืกื˜ื™ืช ืžื‘ื•ื–ืจืช ืžืœืื” ื‘ืžื›ื•ืœื•ืช ืขื•ื™ื ื•ืช.

ื’ื™ืฉื” ื ื‘ื—ืจืช

ืงืœื•ืกื˜ืจ ืžื™ื•ืขื“ ืœื”ืคืขืœื” ื›ืืคืœื™ืงืฆื™ื”, ืื ื›ื™ ืžืฉืชืžืฉื™ื ืžืชืงื“ืžื™ื ื™ื›ื•ืœื™ื ืœืขื‘ื•ื“ ืขื ื”ืจื›ื‘ื” ื•ืชื—ื–ื•ืงื” ืฉืœ ื”ืืฉื›ื•ืœ ื‘ืื•ืคืŸ ื™ื“ื ื™ ืขืœ ื™ื“ื™ ื”ืคืขืœื” ื™ืฉื™ืจื” Cloister.Manager ื‘ืขืฅ ื”ืžืคืงื— ืฉืœ ื™ื™ืฉื•ื ื”ื™ืขื“.

ื›ืืฉืจ ืžืคืขื™ืœื™ื ืื•ืชื• ื›ื™ื™ืฉื•ื, ื”ืกืคืจื™ื™ื” ืžืกืชืžื›ืช ืขืœ config, ืฉืžืžื ื• ื”ื•ื ืงื•ืจื ืืช ื”ืขืจื›ื™ื ื”ื‘ืกื™ืกื™ื™ื ื”ื‘ืื™ื:

config :cloister,
  otp_app: :my_app,
  sentry: :"cloister.local", # or ~w|n1@foo n2@bar|a
  consensus: 3,              # number of nodes to consider
                             #    the cluster is up
  listener: MyApp.Listener   # listener to be called when
                             #    the ring has changed

ื”ืคืจืžื˜ืจื™ื ืฉืœืžืขืœื” ืื•ืžืจื™ื, ืคืฉื•ื˜ื• ื›ืžืฉืžืขื•, ืืช ื”ื“ื‘ืจื™ื ื”ื‘ืื™ื: ืงืœื•ืกื˜ืจ ืžืฉืžืฉ ืขื‘ื•ืจ ื™ื™ืฉื•ื OTP :my_appืฉื™ืžื•ืฉื™ื ื’ื™ืœื•ื™ ืฉื™ืจื•ืช erlang ื›ื“ื™ ืœื—ื‘ืจ ืฆืžืชื™ื, ืœืคื—ื•ืช ืฉืœื•ืฉื”, ื• MyApp.Listener ืžื•ื“ื•ืœ (ื™ื™ืฉื•ื @behaviour Cloister.Listener) ืžื•ื’ื“ืจ ืœืงื‘ืœ ื”ื•ื“ืขื•ืช ืขืœ ืฉื™ื ื•ื™ื™ื ื‘ื˜ื•ืคื•ืœื•ื’ื™ื”. ื ื™ืชืŸ ืœืžืฆื•ื ืชื™ืื•ืจ ืžืคื•ืจื˜ ืฉืœ ื”ืชืฆื•ืจื” ื”ืžืœืื” ื‘ ืชื™ืขื•ื“.

ืขื ืชืฆื•ืจื” ื–ื•, ื”ืืคืœื™ืงืฆื™ื” ืงืœื•ืกื˜ืจ ืจืฆื•ืŸ ื”ืฉืงื” ื‘ืฉืœื‘ื™ื, ืขื™ื›ื•ื‘ ืชื”ืœื™ืš ื”ืชื—ืœืช ื”ื™ื™ืฉื•ื ื”ืจืืฉื™ ืขื“ ืœื”ืฉื’ืช ื”ืกื›ืžื” (ืฉืœื•ืฉื” ืฆืžืชื™ื ืžื—ื•ื‘ืจื™ื ื•ืžื—ื•ื‘ืจื™ื, ื›ืžื• ื‘ื“ื•ื’ืžื” ืœืžืขืœื”.) ื–ื” ื ื•ืชืŸ ืœื™ื™ืฉื•ื ื”ืจืืฉื™ ืืช ื”ื”ื–ื“ืžื ื•ืช ืœื”ื ื™ื— ืฉื›ืืฉืจ ื”ื•ื ืžืชื—ื™ืœ, ื”ืืฉื›ื•ืœ ื›ื‘ืจ ื–ืžื™ืŸ. ื‘ื›ืœ ืคืขื ืฉื”ื˜ื•ืคื•ืœื•ื’ื™ื” ืžืฉืชื ื” (ื™ื”ื™ื• ืจื‘ื™ื ืžื”ื, ืžื›ื™ื•ื•ืŸ ืฉื”ืฆืžืชื™ื ืœื ืžืชื—ื™ืœื™ื ื‘ืื•ืคืŸ ืกื™ื ื›ืจื•ื ื™ ืœื—ืœื•ื˜ื™ืŸ), ื”ืžื˜ืคืœ ื™ื™ืงืจื MyApp.Listener.on_state_change/2. ืœืจื•ื‘ ืื ื• ืžื‘ืฆืขื™ื ืคืขื•ืœื” ื›ืืฉืจ ืื ื• ืžืงื‘ืœื™ื ื”ื•ื“ืขืช ืกื˜ื˜ื•ืก %Cloister.Monitor{status: :up}, ืฉืคื™ืจื•ืฉื•: "ืฉืœื•ื, ื”ืืฉื›ื•ืœ ืžื•ืจื›ื‘."

ื‘ืจื•ื‘ ื”ืžืงืจื™ื, ื”ืชืงื ื” consensus: 3 ื”ื•ื ืื•ืคื˜ื™ืžืœื™ ื›ื™ ื’ื ืื ืื ื• ืžืฆืคื™ื ืฉื™ื•ืชืจ ืฆืžืชื™ื ื™ืชื—ื‘ืจื•, ื”ื”ืชืงืฉืจื•ืช ื—ื–ืจื” ืชืขื‘ื•ืจ status: :rehashing โ†’ status: :up ืขืœ ื›ืœ ืฆื•ืžืช ืฉื ื•ืกืฃ ืื• ื”ื•ืกืจ ืœืื—ืจื•ื ื”.

ื›ืฉืืชื” ืžืชื—ื™ืœ ื‘ืžืฆื‘ ืคื™ืชื•ื—, ืืชื” ืจืง ืฆืจื™ืš ืœื”ื’ื“ื™ืจ consensus: 1 ะธ ืงืœื•ืกื˜ืจ ื™ื“ืœื’ ื‘ืฉืžื—ื” ืขืœ ื”ื”ืžืชื ื” ืœื”ืจื›ื‘ืช ื”ืืฉื›ื•ืœ ื›ืฉื”ื•ื ื™ืจืื” :nonode@nohostืื• :node@hostืื• :[email protected] - ืชืœื•ื™ ืื™ืš ื”ืฆื•ืžืช ื”ื•ื’ื“ืจ (:none | :shortnames | :longnames).

ื ื™ื”ื•ืœ ืืคืœื™ืงืฆื™ื•ืช ืžื‘ื•ื–ืจื•ืช

ื™ื™ืฉื•ืžื™ื ืžื‘ื•ื–ืจื™ื ืฉืื™ื ื ื‘ื•ื•ืืงื•ื ื›ื•ืœืœื™ื ื‘ื“ืจืš ื›ืœืœ ืชืœื•ืช ืžื‘ื•ื–ืจืช, ื›ื’ื•ืŸ mnesia. ืงืœ ืœื ื• ืœื˜ืคืœ ื‘ื”ื’ื“ืจื” ืžื—ื“ืฉ ืฉืœื”ื ืžืื•ืชื” ื”ืชืงืฉืจื•ืช ื—ื•ื–ืจืช on_state_change/2. ื”ื ื”, ืœืžืฉืœ, ืชื™ืื•ืจ ืžืคื•ืจื˜ ื›ื™ืฆื“ ืœื”ื’ื“ื™ืจ ืžื—ื“ืฉ mnesia ืชื•ืš ื›ื“ื™ ืชื ื•ืขื” ืชื™ืขื•ื“ ืงืœื•ืกื˜ืจ.

ื”ื™ืชืจื•ืŸ ื”ืขื™ืงืจื™ ื‘ืฉื™ืžื•ืฉ ืงืœื•ืกื˜ืจ ื”ื•ื ืฉื”ื•ื ืžื‘ืฆืข ืืช ื›ืœ ื”ืคืขื•ืœื•ืช ื”ื“ืจื•ืฉื•ืช ื›ื“ื™ ืœื‘ื ื•ืช ืžื—ื“ืฉ ืืช ื”ืืฉื›ื•ืœ ืœืื—ืจ ืฉื™ื ื•ื™ ื˜ื•ืคื•ืœื•ื’ื™ื” ืžืชื—ืช ืœืžื›ืกืช ื”ืžื ื•ืข. ื”ืืคืœื™ืงืฆื™ื” ืคืฉื•ื˜ ืคื•ืขืœืช ื‘ืกื‘ื™ื‘ื” ืžื‘ื•ื–ืจืช ืžื•ื›ื ื” ื›ื‘ืจ, ื›ืืฉืจ ื›ืœ ื”ืฆืžืชื™ื ืžื—ื•ื‘ืจื™ื, ืœืœื ืงืฉืจ ืื ืื ื• ื™ื•ื“ืขื™ื ืืช ื›ืชื•ื‘ื•ืช ื”-IP ื•ืœื›ืŸ ืืช ืฉืžื•ืช ื”ืฆืžืชื™ื ืžืจืืฉ, ืื• ืฉื”ื ื”ื•ืงืฆื•/ืฉื•ื ื• ื‘ืื•ืคืŸ ื“ื™ื ืžื™. ื–ื” ืœื ืžืฆืจื™ืš ื”ื’ื“ืจื•ืช ืžื™ื•ื—ื“ื•ืช ืฉืœ ืชืฆื•ืจืช Docker ื•ืžื ืงื•ื“ืช ืžื‘ื˜ื• ืฉืœ ืžืคืชื— ื™ื™ืฉื•ืžื™ื, ืื™ืŸ ื”ื‘ื“ืœ ื‘ื™ืŸ ืจื™ืฆื” ื‘ืกื‘ื™ื‘ื” ืžื‘ื•ื–ืจืช ืื• ืจื™ืฆื” ื‘ืกื‘ื™ื‘ื” ืžืงื•ืžื™ืช. :nonode@nohost. ืืชื” ื™ื›ื•ืœ ืœืงืจื•ื ืขื•ื“ ืขืœ ื–ื” ื‘ ืชื™ืขื•ื“.

ืœืžืจื•ืช ืฉื˜ื™ืคื•ืœ ืžื•ืจื›ื‘ ื‘ืฉื™ื ื•ื™ื™ื ื‘ื˜ื•ืคื•ืœื•ื’ื™ื” ืืคืฉืจื™ ื‘ืืžืฆืขื•ืช ื™ื™ืฉื•ื ืžื•ืชืื ืื™ืฉื™ืช MyApp.Listener, ืชืžื™ื“ ื™ื™ืชื›ื ื• ืžืงืจื™ ืงืฆื” ืฉื‘ื”ื ืžื’ื‘ืœื•ืช ื”ืกืคืจื™ื™ื” ื•ื”ื˜ื™ื•ืช ื”ืชืฆื•ืจื” ื”ืœืœื• ืžืชื’ืœื•ืช ื›ืื‘ื ื™ ื”ื™ืกื•ื“ ืฉืœ ื”ื™ื™ืฉื•ื. ื–ื” ื‘ืกื“ืจ, ืคืฉื•ื˜ ืงื— ืืช ื”ืืžื•ืจ ืœืขื™ืœ libcluster, ืฉื”ื•ื ื™ื•ืชืจ ืœืžื˜ืจื•ืช ื›ืœืœื™ื•ืช, ืื• ืืคื™ืœื• ืœื˜ืคืœ ื‘ืืฉื›ื•ืœ ื‘ืจืžื” ื ืžื•ื›ื” ื‘ืขืฆืžืš. ื”ืžื˜ืจื” ืฉืœ ืกืคืจื™ื™ืช ืงื•ื“ ื–ื• ื”ื™ื ืœื ืœื›ืกื•ืช ื›ืœ ืชืจื—ื™ืฉ ืืคืฉืจื™, ืืœื ืœื”ืฉืชืžืฉ ื‘ืชืจื—ื™ืฉ ื”ื ืคื•ืฅ ื‘ื™ื•ืชืจ ืœืœื ื›ืื‘ ืžื™ื•ืชืจ ื•ื”ืขืชืง-ื”ื“ื‘ืง ืžืกื•ืจื‘ืœ.

ื”ืขืจื”: ื‘ืฉืœื‘ ื–ื” ื‘ืžืงื•ืจ ื”ื™ื” ื”ืžืฉืคื˜ "ืืฉื›ื•ืœ ืฉืžื—!", ื•ื™ืื ื“ืงืก, ืฉืื™ืชื• ืื ื™ ืžืชืจื’ื (ืื ื™ ืœื ืฆืจื™ืš ืœืขื‘ื•ืจ ืขืœ ืžื™ืœื•ื ื™ื ื‘ืขืฆืžื™), ื”ืฆื™ืขื” ืœื™ ืืช ื”ืืคืฉืจื•ืช "ืืฉื›ื•ืœ ืฉืžื—!" ืื•ืœื™ ืื™ ืืคืฉืจ ืœื“ืžื™ื™ืŸ ืชืจื’ื•ื ื˜ื•ื‘ ื™ื•ืชืจ, ื‘ืžื™ื•ื—ื“ ืœืื•ืจ ื”ืžืฆื‘ ื”ื’ื™ืื•ืคื•ืœื™ื˜ื™ ื”ื ื•ื›ื—ื™.

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”