Skip to content

Commit

Permalink
Added SYSTEM FORGETALL.
Browse files Browse the repository at this point in the history
  • Loading branch information
jemc committed Aug 10, 2018
1 parent b9fc238 commit c4181b0
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 12 deletions.
10 changes: 10 additions & 0 deletions docs/_docs/types/system.md
Expand Up @@ -20,3 +20,13 @@ The system log is kept trimmed to a fixed maximum length to avoid unbounded memo
Returns an array where each element is a two-element array containing the value and timestamp of that entry.

The values will be returned as string, and the timestamps as integers.

### `FORGETALL`

Clear all data from the local in-memory database for this node. This is intended for use in application testing environments.

If in a cluster, data will remain in the other nodes, meaning that all of the cleared data will be restored locally over time using the normal anti-entropy repair mechanisms - the local node will still be eventually consistent with the rest of the cluster.

This command is not meant to be used in conjunction with disk persistence, but if used when disk persistence is enabled, there are no guarantees about how much of the data will remain present on the local disk in the immediate or short term. However, if in a cluster, eventual consistency guarantees with the other nodes in the cluster will still hold as described in the paragraph above.

Returns a simple string reply of `OK` immediately, while the database is being cleared asynchronously.
6 changes: 6 additions & 0 deletions jylis/database.pony
Expand Up @@ -41,6 +41,12 @@ class val Database
""")
end

fun forget_all() =>
_system.log.info() and _system.log.i("database forgetting all data")
for repo in _map.values() do
repo.forget_all()
end

fun flush_deltas(fn: _NameTokensFn) =>
for repo in _map.values() do
repo.flush_deltas(fn)
Expand Down
2 changes: 1 addition & 1 deletion jylis/main.pony
Expand Up @@ -8,5 +8,5 @@ actor Main
let disk = DiskSetup(system) .> replay(database)
let server = Server(auth, system, database)
let cluster = Cluster(auth, system, database, disk)
system.dispose.setup(database, disk, server, cluster)
system.setup(database, disk, server, cluster)
end
13 changes: 11 additions & 2 deletions jylis/repo_manager.pony
Expand Up @@ -15,6 +15,7 @@ interface RepoAny

interface tag RepoManagerAny
be apply(resp: Respond, cmd: Array[String] val)
be forget_all()
be flush_deltas(fn: _NameTokensFn)
be converge_deltas(deltas: crdt.TokensIterator iso)
be send_data(send_fn: _NameTokensFn)
Expand All @@ -34,6 +35,9 @@ actor RepoManager[R: RepoAny ref, H: HelpLeaf val] is RepoManagerAny
be apply(resp: Respond, cmd: Array[String] val) =>
_core(resp, cmd)

be forget_all() =>
_core.forget_all()

be flush_deltas(fn: _NameTokensFn) =>
_core.flush_deltas(fn)

Expand All @@ -58,13 +62,18 @@ actor RepoManager[R: RepoAny ref, H: HelpLeaf val] is RepoManagerAny

class RepoManagerCore[R: RepoAny ref, H: HelpLeaf val]
let _name: String
let _repo: R
let _identity: U64
var _repo: R
var _deltas_fn: (_NameTokensFn | None) = None
var _last_proactive: U64 = 0
var _shutdown: Bool = false

new create(name': String, identity': U64) =>
(_name, _repo) = (name', R(identity'))
(_name, _identity) = (name', identity')
_repo = R(_identity)

fun ref forget_all() =>
_repo = R(_identity)

fun name(): String => _name
fun repo(): this->R => _repo
Expand Down
11 changes: 10 additions & 1 deletion jylis/repo_system.pony
Expand Up @@ -9,15 +9,18 @@ primitive RepoSYSTEMHelp is HelpLeaf
"""
The following are valid SYSTEM commands:
SYSTEM GETLOG [count]
SYSTEM FORGETALL
"""

class RepoSYSTEM
let _identity: U64
var _database: (Database | None) = None

let _log: TLog[String] = TLog[String]
var _log_delta: TLog[String] = TLog[String]

new create(identity': U64) => _identity = identity'
fun ref setup(database': Database) => _database = database'

fun ref delta_empty(): Bool => _log_delta.is_empty()
fun ref flush_deltas(): Tokens =>
Expand All @@ -39,7 +42,8 @@ class RepoSYSTEM

fun ref apply(r: Respond, cmd: Iterator[String]): Bool? =>
match cmd.next()?
| "GETLOG" => getlog(r, _optcount(cmd))
| "GETLOG" => getlog(r, _optcount(cmd))
| "FORGETALL" => forgetall(r)
else error
end

Expand All @@ -61,6 +65,11 @@ class RepoSYSTEM
end
false

fun forgetall(resp: Respond): Bool =>
try (_database as Database).forget_all() end
resp.ok()
false

///
// System private methods, meant for use only within the jylis server.
// Generally, the purpose is to fill data that is read-only to the user.
Expand Down
26 changes: 18 additions & 8 deletions jylis/system.pony
Expand Up @@ -13,22 +13,26 @@ class val System
dispose = SystemDispose
repo = SystemRepoManager(config)
log = config.log .> set_sys(repo)

actor SystemDispose
var _dispose: (Dispose | None) = None
var _dispose_when_ready: Bool = false

be setup(
fun val setup(
database: Database,
disk: DiskAny,
server: Server,
cluster: Cluster)
=>
_dispose = Dispose(database, disk, server, cluster) .> on_signal()
if _dispose_when_ready then apply() end
dispose.setup(Dispose(database, disk, server, cluster) .> on_signal())
repo.setup(database)

actor SystemDispose
var _dispose: (Dispose | None) = None
var _pending: Bool = false

be setup(dispose': Dispose) =>
_dispose = dispose'
if _pending then apply() end

be apply() =>
try (_dispose as Dispose).dispose() else _dispose_when_ready = true end
try (_dispose as Dispose).dispose() else _pending = true end

actor SystemRepoManager is RepoManagerAny
let _config: Config
Expand All @@ -38,9 +42,15 @@ actor SystemRepoManager is RepoManagerAny
_config = config'
_core = _core.create("SYSTEM", _config.addr.hash64())

be setup(database': Database) =>
_core.repo().setup(database')

be apply(resp: Respond, cmd: Array[String] val) =>
_core(resp, cmd)

be forget_all() =>
None // don't forget any SYSTEM data.

be flush_deltas(fn: _NameTokensFn) =>
_core.flush_deltas(fn)

Expand Down
29 changes: 29 additions & 0 deletions spec/system_spec.rb
@@ -0,0 +1,29 @@
require_relative "spec_helper"

require "securerandom"
require "fileutils"

describe "System functions" do
subject { Jylis.new }

describe "FORGETALL" do
it "saves to and loads from an append-only file with a predictable format" do
subject.run do
subject.call(%w[TREG SET key1 foo 7]).should eq "OK"
subject.call(%w[TREG GET key1]).should eq ["foo", 7]

subject.call(%w[SYSTEM FORGETALL]).should eq "OK"
subject.call(%w[TREG GET key1]).should eq ["", 0]

subject.call(%w[TREG SET key1 bar 8]).should eq "OK"
subject.call(%w[TREG GET key1]).should eq ["bar", 8]

subject.call(%w[SYSTEM FORGETALL]).should eq "OK"
subject.call(%w[TREG GET key1]).should eq ["", 0]

subject.call(%w[TREG SET key1 baz 9]).should eq "OK"
subject.call(%w[TREG GET key1]).should eq ["baz", 9]
end
end
end
end

0 comments on commit c4181b0

Please sign in to comment.