Tôi cần lời khuyên về cấu trúc dữ liệu để sử dụng làm nhật ký thay đổi nguyên tử.Danh sách thân thiện với STM dưới dạng nhật ký thay đổi
Tôi đang cố triển khai thuật toán sau. Có một luồng đến thay đổi cập nhật bản đồ trong bộ nhớ. Trong giả Haskell giống như nó là
update :: DataSet -> SomeListOf Change -> Change -> STM (DataSet, SomeListOf Change)
update dataSet existingChanges newChange = do
...
return (dataSet, existingChanges ++ [newChange])
nơi DataSet là một bản đồ (hiện nay nó là bản đồ từ gói stm-container, https://hackage.haskell.org/package/stm-containers-0.2.10/docs/STMContainers-Map.html). Toàn bộ "cập nhật" được gọi từ số lượng chủ đề tùy ý. Một số thay đổi có thể bị từ chối do ngữ nghĩa của miền, tôi sử dụng throwSTM để loại bỏ hiệu ứng của giao dịch. Trong trường hợp cam kết thành công, "newChange" được thêm vào danh sách.
Tồn tại chủ đề riêng biệt mà gọi hàm sau:
flush :: STM (DataSet, SomeListOf Change) -> IO()
chức năng này được cho là để có những ảnh chụp hiện tại của DataSet kèm theo danh sách các thay đổi (nó có một cặp thống nhất) và tuôn ra nó vào hệ thống tệp, tức là
flush data = do
(dataSet, changes) <- atomically $ readTVar data_
-- write them both to FS
-- ...
atomically $ writeTVar data_ (dataSet, [])
Tôi cần lời khuyên về cấu trúc dữ liệu để sử dụng cho "Thay đổi SomeListOf". Tôi không muốn sử dụng [Thay đổi] vì nó "quá trật tự" và tôi e rằng sẽ có quá nhiều xung đột, điều này sẽ buộc toàn bộ giao dịch phải thử lại. Hãy sửa tôi, nếu tôi sai ở đây.
Tôi không thể sử dụng Set (https://hackage.haskell.org/package/stm-containers-0.2.10/docs/STMContainers-Set.html) vì tôi vẫn cần phải giữ lại một số đơn đặt hàng, ví dụ: thứ tự giao dịch cam kết. Tôi có thể sử dụng TChan cho nó và nó trông giống như một kết hợp tốt (chính xác thứ tự các giao dịch cam kết), nhưng tôi không biết làm thế nào để thực hiện các chức năng "tuôn ra" để nó sẽ cung cấp cho xem nhất quán của toàn bộ nhật ký thay đổi với nhau với DataSet.
Triển khai hiện tại là ở đây https://github.com/lolepezy/rpki-pub-server/blob/add-storage/src/RRDP/Repo.hs, trong các hàm applyActionsToState và rrdpSyncThread, tương ứng. Nó sử dụng TChan và dường như làm điều đó một cách sai lầm.
Cảm ơn bạn trước.
Cập nhật: Một câu trả lời hợp lý có vẻ là như thế
type SomeListOf c = TChan [c]
update :: DataSet -> TChan [Change] -> Change -> STM DataSet
update dataSet existingChanges newChange = do
...
writeTChan changeChan $ reverse (newChange : existingChanges)
return dataSet
flush data_ = do
(dataSet, changes) <- atomically $ (,) <$> readTVar data_ <*> readTChan changeChan
-- write them both to FS
-- ...
Nhưng tôi vẫn không chắc chắn cho dù đó là một giải pháp gọn gàng để vượt qua toàn bộ danh sách như một yếu tố của kênh.
Tôi không đọc kỹ câu hỏi của bạn, nhưng 'TChan' là một hàm dequeue chết đơn giản ([a], [a])'; có vẻ như bạn có thể thực hiện biến thể của riêng bạn trên đó. – jberryman
Hãy để tôi hỏi: Có bao nhiêu chủ đề (ít nhất là một số thô) được dự kiến sẽ truy cập vào cấu trúc? Và bao nhiêu người trong số họ cùng một lúc? Bạn mong đợi bao nhiêu danh sách các thay đổi phát triển? –
Ngoài ra, bạn có cần phải soạn 'cập nhật' với các hoạt động' STM' khác, hay nó luôn chạy trong giao dịch của riêng nó? –