Allow to supply an invalidation key to FileSystemBlobStore

This commit is contained in:
Antonio Scandurra 2015-12-11 13:38:50 +01:00
parent cdd4212400
commit c5562d8446
2 changed files with 54 additions and 31 deletions

View File

@ -9,61 +9,71 @@ describe "FileSystemBlobStore", ->
blobStore = FileSystemBlobStore.load(storageDirectory)
it "is empty when the file doesn't exist", ->
expect(blobStore.get("foo")).toBeUndefined()
expect(blobStore.get("bar")).toBeUndefined()
expect(blobStore.get("foo", "invalidation-key-1")).toBeUndefined()
expect(blobStore.get("bar", "invalidation-key-2")).toBeUndefined()
it "allows to read and write buffers from/to memory without persisting them", ->
blobStore.set("foo", new Buffer("foo"))
blobStore.set("bar", new Buffer("bar"))
blobStore.set("foo", "invalidation-key-1", new Buffer("foo"))
blobStore.set("bar", "invalidation-key-2", new Buffer("bar"))
expect(blobStore.get("foo")).toEqual(new Buffer("foo"))
expect(blobStore.get("bar")).toEqual(new Buffer("bar"))
expect(blobStore.get("foo", "invalidation-key-1")).toEqual(new Buffer("foo"))
expect(blobStore.get("bar", "invalidation-key-2")).toEqual(new Buffer("bar"))
expect(blobStore.get("foo", "unexisting-key")).toBeUndefined()
expect(blobStore.get("bar", "unexisting-key")).toBeUndefined()
it "persists buffers when saved and retrieves them on load, giving priority to in-memory ones", ->
blobStore.set("foo", new Buffer("foo"))
blobStore.set("bar", new Buffer("bar"))
blobStore.set("foo", "invalidation-key-1", new Buffer("foo"))
blobStore.set("bar", "invalidation-key-2", new Buffer("bar"))
blobStore.save()
blobStore = FileSystemBlobStore.load(storageDirectory)
expect(blobStore.get("foo")).toEqual(new Buffer("foo"))
expect(blobStore.get("bar")).toEqual(new Buffer("bar"))
expect(blobStore.get("foo", "invalidation-key-1")).toEqual(new Buffer("foo"))
expect(blobStore.get("bar", "invalidation-key-2")).toEqual(new Buffer("bar"))
expect(blobStore.get("foo", "unexisting-key")).toBeUndefined()
expect(blobStore.get("bar", "unexisting-key")).toBeUndefined()
blobStore.set("foo", new Buffer("changed"))
blobStore.set("foo", "new-key", new Buffer("changed"))
expect(blobStore.get("foo")).toEqual(new Buffer("changed"))
expect(blobStore.get("foo", "new-key")).toEqual(new Buffer("changed"))
expect(blobStore.get("foo", "invalidation-key-1")).toBeUndefined()
it "persists both in-memory and previously stored buffers when saved", ->
blobStore.set("foo", new Buffer("foo"))
blobStore.set("bar", new Buffer("bar"))
blobStore.set("foo", "invalidation-key-1", new Buffer("foo"))
blobStore.set("bar", "invalidation-key-2", new Buffer("bar"))
blobStore.save()
blobStore = FileSystemBlobStore.load(storageDirectory)
blobStore.set("bar", new Buffer("changed"))
blobStore.set("qux", new Buffer("qux"))
blobStore.set("bar", "invalidation-key-3", new Buffer("changed"))
blobStore.set("qux", "invalidation-key-4", new Buffer("qux"))
blobStore.save()
blobStore = FileSystemBlobStore.load(storageDirectory)
expect(blobStore.get("foo")).toEqual(new Buffer("foo"))
expect(blobStore.get("bar")).toEqual(new Buffer("changed"))
expect(blobStore.get("qux")).toEqual(new Buffer("qux"))
expect(blobStore.get("foo", "invalidation-key-1")).toEqual(new Buffer("foo"))
expect(blobStore.get("bar", "invalidation-key-3")).toEqual(new Buffer("changed"))
expect(blobStore.get("qux", "invalidation-key-4")).toEqual(new Buffer("qux"))
expect(blobStore.get("foo", "unexisting-key")).toBeUndefined()
expect(blobStore.get("bar", "invalidation-key-2")).toBeUndefined()
expect(blobStore.get("qux", "unexisting-key")).toBeUndefined()
it "allows to delete keys from both memory and stored buffers", ->
blobStore.set("a", new Buffer("a"))
blobStore.set("b", new Buffer("b"))
blobStore.set("a", "invalidation-key-1", new Buffer("a"))
blobStore.set("b", "invalidation-key-2", new Buffer("b"))
blobStore.save()
blobStore = FileSystemBlobStore.load(storageDirectory)
blobStore.set("b", new Buffer("b"))
blobStore.set("c", new Buffer("c"))
blobStore.set("b", "invalidation-key-3", new Buffer("b"))
blobStore.set("c", "invalidation-key-4", new Buffer("c"))
blobStore.delete("b")
blobStore.delete("c")
blobStore.save()
blobStore = FileSystemBlobStore.load(storageDirectory)
expect(blobStore.get("a")).toEqual(new Buffer("a"))
expect(blobStore.get("b")).toBeUndefined()
expect(blobStore.get("c")).toBeUndefined()
expect(blobStore.get("a", "invalidation-key-1")).toEqual(new Buffer("a"))
expect(blobStore.get("b", "invalidation-key-2")).toBeUndefined()
expect(blobStore.get("b", "invalidation-key-3")).toBeUndefined()
expect(blobStore.get("c", "invalidation-key-4")).toBeUndefined()

View File

@ -13,8 +13,10 @@ class FileSystemBlobStore {
constructor (directory) {
this.inMemoryBlobs = new Map()
this.invalidationKeys = {}
this.blobFilename = path.join(directory, 'BLOB')
this.blobMapFilename = path.join(directory, 'MAP')
this.invalidationKeysFilename = path.join(directory, 'INVKEYS')
this.lockFilename = path.join(directory, 'LOCK')
this.storedBlob = new Buffer(0)
this.storedBlobMap = {}
@ -27,14 +29,19 @@ class FileSystemBlobStore {
if (!fs.existsSync(this.blobFilename)) {
return
}
if (!fs.existsSync(this.invalidationKeysFilename)) {
return
}
this.storedBlob = fs.readFileSync(this.blobFilename)
this.storedBlobMap = JSON.parse(fs.readFileSync(this.blobMapFilename))
this.invalidationKeys = JSON.parse(fs.readFileSync(this.invalidationKeysFilename))
}
save () {
let dump = this.getDump()
let blobToStore = Buffer.concat(dump[0])
let mapToStore = JSON.stringify(dump[1])
let invalidationKeysToStore = JSON.stringify(this.invalidationKeys)
let acquiredLock = false
try {
@ -43,6 +50,7 @@ class FileSystemBlobStore {
fs.writeFileSync(this.blobFilename, blobToStore)
fs.writeFileSync(this.blobMapFilename, mapToStore)
fs.writeFileSync(this.invalidationKeysFilename, invalidationKeysToStore)
} catch (error) {
// Swallow the exception silently only if we fail to acquire the lock.
if (error.code !== 'EEXIST') {
@ -55,15 +63,20 @@ class FileSystemBlobStore {
}
}
has (key) {
return this.inMemoryBlobs.hasOwnProperty(key) || this.storedBlobMap.hasOwnProperty(key)
has (key, invalidationKey) {
let containsKey = this.inMemoryBlobs.has(key) || this.storedBlobMap.hasOwnProperty(key)
let isValid = this.invalidationKeys[key] === invalidationKey
return containsKey && isValid
}
get (key) {
return this.getFromMemory(key) || this.getFromStorage(key)
get (key, invalidationKey) {
if (this.has(key, invalidationKey)) {
return this.getFromMemory(key) || this.getFromStorage(key)
}
}
set (key, buffer) {
set (key, invalidationKey, buffer) {
this.invalidationKeys[key] = invalidationKey
return this.inMemoryBlobs.set(key, buffer)
}