Tôi đã chơi đùa với gói UNIX của conduit-extra
, về cơ bản cho phép tạo một máy chủ dễ dàng bằng cách sử dụng các ổ cắm miền UNIX, cụ thể là sử dụng runUnixServer
funciton.Cách dọn dẹp tài nguyên chính xác bằng cách sử dụng ResourceT là gì?
Vấn đề là sau khi chức năng tồn tại, nó sẽ không dọn dẹp tệp ổ cắm, điều đó có nghĩa là nó cần được dọn dẹp thủ công. Đây là một ví dụ đơn giản, về cơ bản tạo ra một máy chủ echo.
main :: IO()
main = do
let settings = serverSettings "foobar.sock"
runUnixServer settings (\ad -> (appSource ad) $$ (appSink ad))
Tôi đã google một chút và thấy rằng cách chính xác để xử lý tài nguyên ở đây là sử dụng gói resourcet
. Mặc dù vấn đề là hầu hết các API trong tài nguyên mong đợi tôi tự phân bổ tài nguyên, đây không phải là trường hợp của runUnixSever
, không trả về bất kỳ thứ gì.
Lúc đầu, tôi nghĩ tôi có thể sử dụng register
, đăng ký một chức năng mà loại bỏ các tập tin, chẳng hạn như sau
main :: IO()
main = runResourceT $ do
register $ removeLink "foobar.sock"
let settings = serverSettings "foobar.sock"
liftIO $ runUnixServer settings (\ad -> (appSource ad) $$ (appSink ad))
Có một vấn đề với cách tiếp cận này mặc dù, ít nhất là như xa như các tài liệu cho allocate
nói:
Điều này gần giống với việc gọi phân bổ và sau đó đăng ký hành động phát hành, nhưng điều này xử lý đúng cách mặt nạ ngoại lệ không đồng bộ.
Điều này có nghĩa là tự nó không xử lý ngoại lệ không đồng bộ? Nếu vậy, có thể đó là một vấn đề khi một trong những xử lý sinh ra bởi các runUnixServer
(tài liệu nói nó sinh ra một sợi cho mỗi khách hàng) làm tăng một lỗi?
Giải pháp thứ ba và cuối cùng mà tôi đưa ra là sử dụng allocate
, để đảm bảo rằng các ngoại lệ không đồng bộ được xử lý đúng cách (tôi không chắc liệu nó có thực sự cần thiết trong trường hợp này) hay không.
main :: IO()
main = runResourceT $ do
allocate (return 1) (const $ removeLink "foobar.sock")
let settings = serverSettings "foobar.sock"
liftIO $ runUnixServer settings (\ad -> (appSource ad) $$ (appSink ad))
Nhưng đây thực sự là giải pháp tốt nhất? Vì tôi đang tạo một giá trị mà tôi sẽ không bao giờ sử dụng (return 1)
và sau đó sử dụng một hàm const
để bỏ qua giá trị đó trong trình hoàn thiện.
Cảm ơn bạn đã phản hồi cực nhanh! –