2013-01-12 15 views
9

Tôi đang bối rối bởi các cuộc gọi với carmine nên được thực hiện như thế nào. Tôi tìm thấy wcar vĩ mô được mô tả trong carmine's docs:Macro wcar của carmine nên được sử dụng như thế nào?

(defmacro wcar [& body] `(car/with-conn pool spec-server1 [email protected])) 

Tôi thực sự phải gọi wcar mỗi khi tôi muốn nói chuyện với redis ngoài các lệnh redis? Hay tôi có thể gọi nó ngay từ đầu? Nếu thế thì sao?

Đây là những gì một số mã với thư viện redis tavisrudd của trông giống như (từ TestSuite shortener dự án url đồ chơi của tôi):

(deftest test_shorten_doesnt_exist_create_new_next 
    (redis/with-server test-server 
    (redis/set "url_counter" 51) 
    (shorten test-url) 
    (is (= "1g" (redis/get (str "urls|" test-url)))) 
    (is (= test-url (redis/get "shorts|1g"))))) 

Và bây giờ tôi chỉ có thể làm cho nó làm việc với thoa son bằng cách viết nó như thế này:

(deftest test_shorten_doesnt_exist_create_new_next 
    (wcar (car/set "url_counter" 51)) 
    (shorten test-url) 
    (is (= "1g" (wcar (car/get (str "urls|" test-url))))) 
    (is (= test-url (wcar (car/get "shorts|1g"))))) 

Vậy cách sử dụng đúng cách và khái niệm cơ bản nào tôi không nhận được?

Trả lời

8

Giải thích của Dan là chính xác.

Carmine sử dụng đường ống phản hồi theo mặc định, trong khi redis-clojure yêu cầu bạn yêu cầu pipelining khi bạn muốn (sử dụng macro pipeline).

Lý do chính bạn muốn pipelining là hiệu suất. Redis nhanh đến nỗi nút cổ chai trong việc sử dụng nó thường là thời gian cần thiết cho yêu cầu + phản hồi để di chuyển qua mạng.

Clojure destructuring cung cấp cách thuận tiện để giải quyết phản hồi pipelined, nhưng yêu cầu viết mã của bạn khác với redis-clojure. Con đường tôi muốn viết ví dụ của bạn là một cái gì đó như thế này (tôi giả sử shorten fn của bạn có tác dụng phụ và cần phải được gọi trước khi GET s):

(deftest test_shorten_doesnt_exist_create_new_next 
    (wcar (car/set "url_counter" 51)) 
    (shorten test-url) 
    (let [[response1 response2] (wcar (car/get (str "urls|" test-url)) 
            (car/get "shorts|1g"))] 
    (is (= "1g" response1)) 
    (is (= test-url response2)))) 

Vì vậy, chúng tôi đang gửi người đầu tiên (SET) yêu cầu Redis và chờ trả lời (Tôi không chắc chắn nếu điều đó thực sự cần thiết ở đây). Sau đó chúng tôi gửi hai yêu cầu tiếp theo (GET) cùng một lúc, cho phép Redis xếp hàng các phản hồi, sau đó nhận lại tất cả chúng cùng một lúc như một vectơ mà chúng tôi sẽ hủy cấu trúc. Lúc đầu, điều này có vẻ như nỗ lực không cần thiết vì nó đòi hỏi bạn phải rõ ràng về thời điểm nhận phản hồi xếp hàng, nhưng nó mang lại nhiều lợi ích bao gồm hiệu suất, độ rõ ràng và composable commands.

Tôi muốn kiểm tra Touchstone trên GitHub nếu bạn đang tìm kiếm một ví dụ về những gì tôi muốn xem xét thành ngữ Carmine sử dụng (chỉ cần tìm kiếm các cuộc gọi wcar). (Xin lỗi, SO đang ngăn tôi đưa liên kết khác).

Nếu không, chỉ cần bật email cho tôi (hoặc gửi vấn đề GitHub) nếu bạn có bất kỳ câu hỏi nào khác.

+0

Cảm ơn rất nhiều. Bây giờ tôi hiểu lý do tại sao phương pháp này là tốt hơn bởi vì nó làm cho nó rõ ràng khi kết nối thực sự xảy ra. – Oin

5

Đừng lo lắng, bạn đang sử dụng đúng cách.

Các chức năng yêu cầu Redis (chẳng hạn như nhận và thiết lập bạn đang sử dụng ở trên) đều được định tuyến thông qua chức năng khác send-request! dựa trên một liên kết động *context* để cung cấp kết nối. Cố gắng gọi bất kỳ lệnh Redis nào không có ngữ cảnh đó sẽ thất bại với lỗi "không có ngữ cảnh". Macro with-conn (được sử dụng trong wcar) đặt ngữ cảnh đó và cung cấp kết nối.

Macro wcar sau đó chỉ là một trình bao bọc mỏng xung quanh with-conn giả định rằng bạn sẽ sử dụng cùng một chi tiết kết nối cho tất cả các yêu cầu Redis.

Cho đến nay điều này rất giống với cách hoạt động của công trình redis-clojure của Tavis Rudd.

Vì vậy, câu hỏi bây giờ là tại sao Carmine cần nhiều wcar khi Redis-Clojure chỉ yêu cầu một with-server?

Và câu trả lời là không. Ngoài đôi khi, khi có. Số with-conn của Carmine sử dụng số "Pipelining" của Redis để gửi nhiều yêu cầu với cùng một kết nối và sau đó gói các phản hồi lại với nhau trong một vectơ. Ví dụ từ README cho thấy điều này trong hành động.

(wcar (car/ping) 
     (car/set "foo" "bar") 
     (car/get "foo")) 
=> ["PONG" "OK" "bar"] 

Ở đây bạn sẽ thấy rằng ping, setget là chỉ quan tâm đến gửi yêu cầu, để lại nhận phản ứng lên đến wcar. Điều này ngăn cản các xác nhận (hoặc bất kỳ truy cập kết quả nào) từ bên trong của wcar và dẫn đến việc tách các yêu cầu và nhiều cuộc gọi wcar mà bạn có.

+0

Cảm ơn. Có cách nào để có một cái gì đó giống như chức năng của redis-clojure với carmine? I E. chỉ nói ngữ cảnh mà tôi muốn sử dụng một lần cho mỗi khối mã lớn? Giống như trong ví dụ với trường hợp thử nghiệm? – Oin

+0

Loại. Nhưng bạn có thể không hài lòng với nó. Bạn có thể đặt tất cả nhưng các xác nhận bên trong một khối xe. Các phản ứng từ Redis sẽ được trả về từ wcar dưới dạng một vectơ và các xác nhận của bạn sẽ cần phải hành động chống lại điều đó. Tôi không thể nói từ mã những gì 'shorten' chức năng của bạn đạt được nhưng bạn nên ok để chạy đó (cũng như bất kỳ chức năng khác) bên trong wcar. –

+0

Tôi nên thêm điều đó, mặc dù điều đó là có thể, điều đó không có nghĩa là tôi khuyên bạn nên sử dụng nó. Tôi thực sự sẽ đề nghị giữ phạm vi wcar nhỏ như nó có thể được. –

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