| defmodule ViewCompactionTest do |
| use CouchTestCase |
| |
| @moduledoc """ |
| Test CouchDB View Compaction Behavior |
| This is a port of the view_compaction.js suite |
| """ |
| @num_docs 1000 |
| |
| @ddoc %{ |
| _id: "_design/foo", |
| language: "javascript", |
| views: %{ |
| view1: %{ |
| map: "function(doc) { emit(doc._id, doc.value) }" |
| }, |
| view2: %{ |
| map: |
| "function(doc) { if (typeof(doc.integer) === 'number') {emit(doc._id, doc.integer);} }", |
| reduce: "function(keys, values, rereduce) { return sum(values); }" |
| } |
| } |
| } |
| |
| defp bulk_save_for_update(db_name, docs) do |
| resp = bulk_save(db_name, docs) |
| revs = resp.body |
| |
| Enum.map(docs, fn m -> |
| rev = Enum.at(revs, String.to_integer(m["_id"]))["rev"] |
| |
| m |
| |> Map.put("_rev", rev) |
| |> Map.update!("integer", &(&1 + 1)) |
| end) |
| end |
| |
| @tag :with_db |
| test "view compaction", context do |
| db_name = context[:db_name] |
| create_doc(db_name, @ddoc) |
| |
| docs = make_docs(0..(@num_docs - 1)) |
| docs = bulk_save_for_update(db_name, docs) |
| |
| resp = view(db_name, "foo/view1") |
| assert length(resp.body["rows"]) == @num_docs |
| |
| resp = view(db_name, "foo/view2") |
| assert length(resp.body["rows"]) == 1 |
| |
| resp = Couch.get("/#{db_name}/_design/foo/_info") |
| assert resp.body["view_index"]["update_seq"] == @num_docs + 1 |
| |
| docs = bulk_save_for_update(db_name, docs) |
| |
| resp = view(db_name, "foo/view1") |
| assert length(resp.body["rows"]) == @num_docs |
| |
| resp = view(db_name, "foo/view2") |
| assert length(resp.body["rows"]) == 1 |
| |
| resp = Couch.get("/#{db_name}/_design/foo/_info") |
| assert resp.body["view_index"]["update_seq"] == 2 * @num_docs + 1 |
| |
| bulk_save(db_name, docs) |
| resp = view(db_name, "foo/view1") |
| assert length(resp.body["rows"]) == @num_docs |
| |
| resp = view(db_name, "foo/view2") |
| assert length(resp.body["rows"]) == 1 |
| |
| resp = Couch.get("/#{db_name}/_design/foo/_info") |
| assert resp.body["view_index"]["update_seq"] == 3 * @num_docs + 1 |
| |
| disk_size_before_compact = resp.body["view_index"]["sizes"]["file"] |
| data_size_before_compact = resp.body["view_index"]["sizes"]["active"] |
| |
| assert is_integer(disk_size_before_compact) |
| assert data_size_before_compact < disk_size_before_compact |
| |
| resp = Couch.post("/#{db_name}/_compact/foo") |
| assert resp.body["ok"] == true |
| |
| retry_until(fn -> |
| resp = Couch.get("/#{db_name}/_design/foo/_info") |
| resp.body["view_index"]["compact_running"] == false |
| end) |
| |
| resp = view(db_name, "foo/view1") |
| assert length(resp.body["rows"]) == @num_docs |
| |
| resp = view(db_name, "foo/view2") |
| assert length(resp.body["rows"]) == 1 |
| |
| resp = Couch.get("/#{db_name}/_design/foo/_info") |
| assert resp.body["view_index"]["update_seq"] == 3 * @num_docs + 1 |
| |
| disk_size_after_compact = resp.body["view_index"]["sizes"]["file"] |
| data_size_after_compact = resp.body["view_index"]["sizes"]["active"] |
| assert disk_size_after_compact < disk_size_before_compact |
| assert is_integer(data_size_after_compact) |
| assert data_size_after_compact < disk_size_after_compact |
| end |
| end |