فهرست منبع

Store docs' metadata in meta.json files

To avoid relying on the filesystem for modified times.
Thibaut Courouble 7 سال پیش
والد
کامیت
0725a69af5
4فایلهای تغییر یافته به همراه48 افزوده شده و 60 حذف شده
  1. 14 0
      lib/docs/core/doc.rb
  2. 3 21
      lib/docs/core/manifest.rb
  3. 21 0
      test/lib/docs/core/doc_test.rb
  4. 10 39
      test/lib/docs/core/manifest_test.rb

+ 14 - 0
lib/docs/core/doc.rb

@@ -2,6 +2,7 @@ module Docs
   class Doc
     INDEX_FILENAME = 'index.json'
     DB_FILENAME = 'db.json'
+    META_FILENAME = 'meta.json'
 
     class << self
       include Instrumentable
@@ -73,6 +74,10 @@ module Docs
         File.join path, DB_FILENAME
       end
 
+      def meta_path
+        File.join path, META_FILENAME
+      end
+
       def as_json
         json = { name: name, slug: slug, type: type }
         json[:links] = links if links.present?
@@ -107,6 +112,7 @@ module Docs
           if index.present?
             store_index(store, INDEX_FILENAME, index)
             store_index(store, DB_FILENAME, pages)
+            store_meta(store)
             true
           else
             false
@@ -131,8 +137,16 @@ module Docs
         instrument "#{filename.remove('.json')}.doc", before: old_json, after: new_json
         store.write(filename, new_json)
       end
+
+      def store_meta(store)
+        json = as_json
+        json[:mtime] = Time.now.to_i
+        json[:db_size] = store.size(DB_FILENAME)
+        store.write(META_FILENAME, json.to_json)
+      end
     end
 
+
     def initialize
       raise NotImplementedError, "#{self.class} is an abstract class and cannot be instantiated." if self.class.abstract
     end

+ 3 - 21
lib/docs/core/manifest.rb

@@ -14,32 +14,14 @@ module Docs
     end
 
     def as_json
-      indexed_docs.map do |doc|
-        json = doc.as_json
-        json[:mtime] = doc_mtime(doc)
-        json[:db_size] = doc_db_size(doc)
-        json
+      @docs.each_with_object [] do |doc, result|
+        next unless @store.exist?(doc.meta_path)
+        result << JSON.parse(@store.read(doc.meta_path))
       end
     end
 
     def to_json
       JSON.generate(as_json)
     end
-
-    private
-
-    def indexed_docs
-      @docs.select do |doc|
-        @store.exist?(doc.index_path) && @store.exist?(doc.db_path)
-      end
-    end
-
-    def doc_mtime(doc)
-      [@store.mtime(doc.index_path).to_i, @store.mtime(doc.db_path).to_i].max
-    end
-
-    def doc_db_size(doc)
-      @store.size(doc.db_path)
-    end
   end
 end

+ 21 - 0
test/lib/docs/core/doc_test.rb

@@ -131,6 +131,13 @@ class DocsDocTest < MiniTest::Spec
     end
   end
 
+  describe ".meta_path" do
+    it "returns .path + ::META_FILENAME" do
+      stub(doc).path { 'path' }
+      assert_equal File.join('path', Docs::Doc::META_FILENAME), doc.meta_path
+    end
+  end
+
   describe ".new" do
     it "raises an error when .abstract is true" do
       doc.abstract = true
@@ -265,12 +272,14 @@ class DocsDocTest < MiniTest::Spec
           mock(store).write(page[:store_path], page[:output])
           mock(store).write('index.json', anything)
           mock(store).write('db.json', anything)
+          mock(store).write('meta.json', anything)
           doc.store_pages(store)
         end
 
         it "stores an index that contains all the pages' entries" do
           stub(store).write(page[:store_path], page[:output])
           stub(store).write('db.json', anything)
+          stub(store).write('meta.json', anything)
           mock(store).write('index.json', anything) do |path, json|
             json = JSON.parse(json)
             assert_equal pages.length, json['entries'].length
@@ -282,6 +291,7 @@ class DocsDocTest < MiniTest::Spec
         it "stores a db that contains all the pages, indexed by path" do
           stub(store).write(page[:store_path], page[:output])
           stub(store).write('index.json', anything)
+          stub(store).write('meta.json', anything)
           mock(store).write('db.json', anything) do |path, json|
             json = JSON.parse(json)
             assert_equal page[:output], json[page[:path]]
@@ -289,6 +299,17 @@ class DocsDocTest < MiniTest::Spec
           doc.store_pages(store)
         end
 
+        it "stores a meta file that contains the doc's metadata" do
+          stub(store).write(page[:store_path], page[:output])
+          stub(store).write('index.json', anything)
+          stub(store).write('db.json', anything)
+          mock(store).write('meta.json', anything) do |path, json|
+            json = JSON.parse(json)
+            assert_equal %w(name slug type mtime db_size).sort, json.keys.sort
+          end
+          doc.store_pages(store)
+        end
+
         it "replaces the .path directory before storing the files" do
           stub(doc).path { 'path' }
           stub(store).write { assert false }

+ 10 - 39
test/lib/docs/core/manifest_test.rb

@@ -41,17 +41,12 @@ class ManifestTest < MiniTest::Spec
   end
 
   describe "#as_json" do
-    let :index_path do
-      'index_path'
-    end
-
-    let :db_path do
-      'db_path'
+    let :meta_path do
+      'meta_path'
     end
 
     before do
-      stub(doc).index_path { index_path }
-      stub(doc).db_path { db_path }
+      stub(doc).meta_path { meta_path }
     end
 
     it "returns an array" do
@@ -59,46 +54,22 @@ class ManifestTest < MiniTest::Spec
       assert_instance_of Array, manifest.as_json
     end
 
-    context "when the doc has an index and a db" do
+    context "when the doc has a meta file" do
       before do
-        stub(store).exist?(index_path) { true }
-        stub(store).exist?(db_path) { true }
+        stub(store).exist?(meta_path) { true }
+        stub(store).read(meta_path) { '{"name":"Test"}' }
       end
 
-      it "includes the doc's JSON representation" do
+      it "includes the doc's meta representation" do
         json = manifest.as_json
         assert_equal 1, json.length
-        assert_empty doc.as_json.keys - json.first.keys
-      end
-
-      it "adds an :mtime attribute with the greatest of the index and db files' mtime" do
-        mtime_index = Time.now - 1
-        mtime_db = Time.now - 2
-        stub(store).mtime(index_path) { mtime_index }
-        stub(store).mtime(db_path) { mtime_db }
-        assert_equal mtime_index.to_i, manifest.as_json.first[:mtime]
-        mtime_index, mtime_db = mtime_db, mtime_index
-        assert_equal mtime_db.to_i, manifest.as_json.first[:mtime]
-      end
-
-      it "adds a :db_size attribute" do
-        stub(store).size(db_path) { 42 }
-        assert_equal 42, manifest.as_json.first[:db_size]
-      end
-    end
-
-    context "when the doc doesn't have an index" do
-      it "doesn't include the doc" do
-        stub(store).exist?(db_path) { true }
-        stub(store).exist?(index_path) { false }
-        assert_empty manifest.as_json
+        assert_equal 'Test', json[0]['name']
       end
     end
 
-    context "when the doc doesn't have a db" do
+    context "when the doc doesn't have a meta file" do
       it "doesn't include the doc" do
-        stub(store).exist?(index_path) { true }
-        stub(store).exist?(db_path) { false }
+        stub(store).exist?(meta_path) { false }
         assert_empty manifest.as_json
       end
     end