2014-11-17 15 views
6

Tôi có một dự án kết hợp đơn giản nhất có thể với Giám sát và Máy chủ GenServer. Khi tôi gọi từ iex:Làm thế nào để chạy Giám sát Elixir theo số

EchoCmd.Supervisor.start_link([:Hello]) 
GenServer.call(:echoserver, :echo) 
GenServer.call(:echoserver, :mumble) 
GenServer.call(:echoserver, :echo) 

: cuộc gọi nhảm sẽ đưa ra ngoại lệ, khi đó GenServer được khởi động lại và cuộc gọi thứ hai: echo hoạt động ok.

Nếu tôi chạy mã theo bất kỳ cách nào khác, Trình giám sát không khởi động được GenServer. Ví dụ, tôi tạo ra một escript của dự án với các module chính như sau:

defmodule EchoCmd.Echo do 
    def main(args) do 
     EchoCmd.Supervisor.start_link([:Hello]) 
     GenServer.call(:echoserver, :echo) 
     GenServer.call(:echoserver, :mumble) 
     GenServer.call(:echoserver, :echo) 
    end 
end 

Các: gọi lí nhí đặt ra một ngoại lệ và escript chấm dứt mà không có sự giám sát khởi động lại GenServer.

Tôi không đưa mã giám sát và mô-đun máy chủ vì chúng hoạt động tốt khi được gọi từ iex, vì vậy tôi đoán chúng không cần thiết ở đây.

Tôi có hiểu lầm không? Điều này là không thể, hoặc tôi đang làm điều gì sai?

Trả lời

5

Vấn đề không nằm ở máy chủ và người giám sát của bạn, nhưng trong cách bạn đang gọi họ. Nếu máy chủ thoát trong khi một quá trình khác đang chờ trả lời GenServer.call, quá trình gọi cũng sẽ thoát, do đó cuộc gọi cuối cùng sẽ không bao giờ xảy ra. Lý do cho điều này là quá trình không thể tiếp tục ở trạng thái không hợp lệ nếu cuộc gọi đồng bộ không thành công (GenServer.call là đồng bộ thay vì GenServer.cast). Nếu bạn đang làm điều này chỉ để kiểm tra giám sát, sau đó bạn có thể thử:

defmodule EchoCmd.Echo do 
    def main(args) do 
     EchoCmd.Supervisor.start_link([:Hello]) 
     GenServer.cast(:echoserver, :echo) 
     GenServer.cast(:echoserver, :mumble) 
     GenServer.cast(:echoserver, :echo) 
    end 
end 

Lý do nó hoạt động trong iexiex bẫy lối ra và cho phép bạn gõ vào dòng khác.

+1

Ok, sau nhiều bumbling xung quanh và yak cạo râu, đây là vấn đề của tôi, cùng với không đủ: timer.sleeps. Tôi có thể làm với chế độ noobie để thêm chúng sau mọi thứ. Escript của tôi bị treo ra từ: lầm bầm nếu tôi sử dụng GenServer.start, nhưng nếu tôi sử dụng GenServer.start_link nó báo cáo lỗi và tiếp tục với một GenServer khởi động lại. Tôi hiểu nó nên làm việc theo cách khác xung quanh nhưng tôi sẽ đọc lên. Cảm ơn. –

3

Hành vi Escript là chính xác. Bạn chỉ cần bỏ lỡ cách iex shell "giúp bạn".

Việc bạn đang làm trong mã của mình đang bắt đầu một quá trình được liên kết được liên kết và hơn là bị lỗi. Và vì nó là một quá trình liên kết, khi nó đi xuống, nó giả sử để làm giảm tất cả các quy trình liên kết. Có thể có một số "ngoại lệ", nhưng đó là những gì đang xảy ra với quá trình escript của bạn.

Cả giám sát viên vỏ và giám sát có thể xử lý thông báo "Tôi đã chết, vì vậy bạn nên". Họ làm điều đó bằng cách thay đổi quá trình (quá trình liên kết, không phải là quá trình chết) xử lý các thông điệp như vậy. Nó cho phép họ nhận chúng như những thông điệp bình thường (mà bạn có thể nhận được trong mệnh đề receive nếu bạn muốn) thay vì những điều đặc biệt, nội bộ. Để thay đổi bahaviour này, họ sử dụng Process.flag(:trap_exit, :true) (elixir doc trỏ đến eralng's one). Nó cho phép vỏ chỉ in chết của các quá trình bị giết, thay vì chết mỗi khi bạn làm điều gì đó xấu.

Vì vậy, bạn có thể làm điều tương tự. Thay đổi cờ này và nếu bạn không phù hợp với mẫu trong receive trên các thư đó. Nhưng tôi không nghĩ đó là những gì bạn đang tìm kiếm. Vì quá trình của bạn là singleton và người giám sát thực hiện tất cả khởi động lại, bạn không thực sự có bất kỳ lý do gì để liên kết đến nó ngay từ đầu. Không cần cập nhật về cái chết và khởi động lại, chỉ cần để người giám sát lo lắng về điều đó. Giống như Joe Armstrong đã nói (có thể là diễn giải)

Bạn không cần biết cách sửa máy bán hàng tự động để sử dụng nó.

Vì vậy, chỉ start, thay vì start_link.

Điều đó nói rằng, bạn có thể cân nhắc việc tạo liên kết với người giám sát, điều này cũng có thể chết sau quá nhiều lần khởi động lại (có thể anh ta được yêu cầu cư xử theo cách đó). Và nó cho phép bạn đưa anh ta (và quá trình giám sát) khi bạn chết. Hoặc anh ta có thể được liên kết với người giám sát của bạn, hoặc người giám sát ứng dụng, hoặc theo cách khác. Nó phụ thuộc vào tên miền của bạn, và không có quyết định xấu, bạn chỉ cần kiểm tra những gì làm việc cho bạn.Đó là quyết định thiết kế, và bạn có thể sở để thử nghiệm hoặc đọc thêm về nó:

http://elixir-lang.org/getting_started/mix_otp/5.html

http://www.erlang.org/doc/design_principles/des_princ.html

http://learnyousomeerlang.com/supervisors

Các vấn đề liên quan