Skip to content

Commit 0725a69

Browse files
committed
Store docs' metadata in meta.json files
To avoid relying on the filesystem for modified times.
1 parent ed12d86 commit 0725a69

4 files changed

Lines changed: 48 additions & 60 deletions

File tree

lib/docs/core/doc.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ module Docs
22
class Doc
33
INDEX_FILENAME = 'index.json'
44
DB_FILENAME = 'db.json'
5+
META_FILENAME = 'meta.json'
56

67
class << self
78
include Instrumentable
@@ -73,6 +74,10 @@ def db_path
7374
File.join path, DB_FILENAME
7475
end
7576

77+
def meta_path
78+
File.join path, META_FILENAME
79+
end
80+
7681
def as_json
7782
json = { name: name, slug: slug, type: type }
7883
json[:links] = links if links.present?
@@ -107,6 +112,7 @@ def store_pages(store)
107112
if index.present?
108113
store_index(store, INDEX_FILENAME, index)
109114
store_index(store, DB_FILENAME, pages)
115+
store_meta(store)
110116
true
111117
else
112118
false
@@ -131,8 +137,16 @@ def store_index(store, filename, index)
131137
instrument "#{filename.remove('.json')}.doc", before: old_json, after: new_json
132138
store.write(filename, new_json)
133139
end
140+
141+
def store_meta(store)
142+
json = as_json
143+
json[:mtime] = Time.now.to_i
144+
json[:db_size] = store.size(DB_FILENAME)
145+
store.write(META_FILENAME, json.to_json)
146+
end
134147
end
135148

149+
136150
def initialize
137151
raise NotImplementedError, "#{self.class} is an abstract class and cannot be instantiated." if self.class.abstract
138152
end

lib/docs/core/manifest.rb

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,32 +14,14 @@ def store
1414
end
1515

1616
def as_json
17-
indexed_docs.map do |doc|
18-
json = doc.as_json
19-
json[:mtime] = doc_mtime(doc)
20-
json[:db_size] = doc_db_size(doc)
21-
json
17+
@docs.each_with_object [] do |doc, result|
18+
next unless @store.exist?(doc.meta_path)
19+
result << JSON.parse(@store.read(doc.meta_path))
2220
end
2321
end
2422

2523
def to_json
2624
JSON.generate(as_json)
2725
end
28-
29-
private
30-
31-
def indexed_docs
32-
@docs.select do |doc|
33-
@store.exist?(doc.index_path) && @store.exist?(doc.db_path)
34-
end
35-
end
36-
37-
def doc_mtime(doc)
38-
[@store.mtime(doc.index_path).to_i, @store.mtime(doc.db_path).to_i].max
39-
end
40-
41-
def doc_db_size(doc)
42-
@store.size(doc.db_path)
43-
end
4426
end
4527
end

test/lib/docs/core/doc_test.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,13 @@ class DocsDocTest < MiniTest::Spec
131131
end
132132
end
133133

134+
describe ".meta_path" do
135+
it "returns .path + ::META_FILENAME" do
136+
stub(doc).path { 'path' }
137+
assert_equal File.join('path', Docs::Doc::META_FILENAME), doc.meta_path
138+
end
139+
end
140+
134141
describe ".new" do
135142
it "raises an error when .abstract is true" do
136143
doc.abstract = true
@@ -265,12 +272,14 @@ class DocsDocTest < MiniTest::Spec
265272
mock(store).write(page[:store_path], page[:output])
266273
mock(store).write('index.json', anything)
267274
mock(store).write('db.json', anything)
275+
mock(store).write('meta.json', anything)
268276
doc.store_pages(store)
269277
end
270278

271279
it "stores an index that contains all the pages' entries" do
272280
stub(store).write(page[:store_path], page[:output])
273281
stub(store).write('db.json', anything)
282+
stub(store).write('meta.json', anything)
274283
mock(store).write('index.json', anything) do |path, json|
275284
json = JSON.parse(json)
276285
assert_equal pages.length, json['entries'].length
@@ -282,13 +291,25 @@ class DocsDocTest < MiniTest::Spec
282291
it "stores a db that contains all the pages, indexed by path" do
283292
stub(store).write(page[:store_path], page[:output])
284293
stub(store).write('index.json', anything)
294+
stub(store).write('meta.json', anything)
285295
mock(store).write('db.json', anything) do |path, json|
286296
json = JSON.parse(json)
287297
assert_equal page[:output], json[page[:path]]
288298
end
289299
doc.store_pages(store)
290300
end
291301

302+
it "stores a meta file that contains the doc's metadata" do
303+
stub(store).write(page[:store_path], page[:output])
304+
stub(store).write('index.json', anything)
305+
stub(store).write('db.json', anything)
306+
mock(store).write('meta.json', anything) do |path, json|
307+
json = JSON.parse(json)
308+
assert_equal %w(name slug type mtime db_size).sort, json.keys.sort
309+
end
310+
doc.store_pages(store)
311+
end
312+
292313
it "replaces the .path directory before storing the files" do
293314
stub(doc).path { 'path' }
294315
stub(store).write { assert false }

test/lib/docs/core/manifest_test.rb

Lines changed: 10 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -41,64 +41,35 @@ class ManifestTest < MiniTest::Spec
4141
end
4242

4343
describe "#as_json" do
44-
let :index_path do
45-
'index_path'
46-
end
47-
48-
let :db_path do
49-
'db_path'
44+
let :meta_path do
45+
'meta_path'
5046
end
5147

5248
before do
53-
stub(doc).index_path { index_path }
54-
stub(doc).db_path { db_path }
49+
stub(doc).meta_path { meta_path }
5550
end
5651

5752
it "returns an array" do
5853
manifest = Docs::Manifest.new store, []
5954
assert_instance_of Array, manifest.as_json
6055
end
6156

62-
context "when the doc has an index and a db" do
57+
context "when the doc has a meta file" do
6358
before do
64-
stub(store).exist?(index_path) { true }
65-
stub(store).exist?(db_path) { true }
59+
stub(store).exist?(meta_path) { true }
60+
stub(store).read(meta_path) { '{"name":"Test"}' }
6661
end
6762

68-
it "includes the doc's JSON representation" do
63+
it "includes the doc's meta representation" do
6964
json = manifest.as_json
7065
assert_equal 1, json.length
71-
assert_empty doc.as_json.keys - json.first.keys
72-
end
73-
74-
it "adds an :mtime attribute with the greatest of the index and db files' mtime" do
75-
mtime_index = Time.now - 1
76-
mtime_db = Time.now - 2
77-
stub(store).mtime(index_path) { mtime_index }
78-
stub(store).mtime(db_path) { mtime_db }
79-
assert_equal mtime_index.to_i, manifest.as_json.first[:mtime]
80-
mtime_index, mtime_db = mtime_db, mtime_index
81-
assert_equal mtime_db.to_i, manifest.as_json.first[:mtime]
82-
end
83-
84-
it "adds a :db_size attribute" do
85-
stub(store).size(db_path) { 42 }
86-
assert_equal 42, manifest.as_json.first[:db_size]
87-
end
88-
end
89-
90-
context "when the doc doesn't have an index" do
91-
it "doesn't include the doc" do
92-
stub(store).exist?(db_path) { true }
93-
stub(store).exist?(index_path) { false }
94-
assert_empty manifest.as_json
66+
assert_equal 'Test', json[0]['name']
9567
end
9668
end
9769

98-
context "when the doc doesn't have a db" do
70+
context "when the doc doesn't have a meta file" do
9971
it "doesn't include the doc" do
100-
stub(store).exist?(index_path) { true }
101-
stub(store).exist?(db_path) { false }
72+
stub(store).exist?(meta_path) { false }
10273
assert_empty manifest.as_json
10374
end
10475
end

0 commit comments

Comments
 (0)