antietcd
Version:
Simplistic etcd replacement based on TinyRaft
129 lines (110 loc) • 4.28 kB
JavaScript
// AntiEtcd server application
// (c) Vitaliy Filippov, 2024
// License: Mozilla Public License 2.0 or Vitastor Network Public License 1.1
const AntiEtcd = require('./antietcd.js');
const help_text = `Miniature etcd replacement based on TinyRaft
(c) Vitaliy Filippov, 2024
License: Mozilla Public License 2.0 or Vitastor Network Public License 1.1
Usage:
${process.argv[0]} ${process.argv[1]} \n\
[--cert ssl.crt] [--key ssl.key] [--port 12379] \n\
[--data data.gz] [--persist-filter ./filter.js] [--persist_interval 500] \n\
[--node_id node1 --cluster_key abcdef --cluster node1=http://localhost:12379,node2=http://localhost:12380,node3=http://localhost:12381] \n\
[]
Supported etcd REST APIs:
/v3/kv/txn /v3/kv/put /v3/kv/range /v3/kv/deleterange
/v3/lease/grant /v3/lease/keepalive /v3/lease/revoke /v3/kv/lease/revoke
websocket-based watch API (create_request, cancel_request, progress_request)
Options:
HTTP:
--port 2379
Listen port
--ip 192.168.0.10
Listen address (by default listen on all interfaces)
--cert <cert>
Use TLS with this certificate file (PEM format)
--key <key>
Use TLS with this key file (PEM format)
--ca <ca>
Use trusted root certificates from this file.
Specify <ca> = <cert> if your certificate is self-signed.
--client_cert_auth 1
Require TLS client certificates signed by <ca> or by default CA to connect.
--ws_keepalive_interval 30000
Client websocket ping (keepalive) interval in milliseconds
--merge_watches 1
Antietcd merges all watcher events into a single websocket message to provide
more ordering/transaction guarantees. Set to 0 to disable this behaviour.
--use_base64 1
Use base64 encoding of keys and values, like in etcd (enabled by default).
Persistence:
--data <filename>
Store persistent data in <filename>
--persist_interval <milliseconds>
Persist data on disk after this interval, not immediately after change
--persist_filter ./filter.js
Use persistence filter from ./filter.js (or a module).
Persistence filter is a function(cfg) returning function(key, value) ran
for every change and returning a new value or undefined to skip persistence.
--compact_revisions 1000
Number of previous revisions to keep deletion information in memory
Clustering:
--node_id <id>
ID of this cluster node
--cluster <id1>=<url1>,<id2>=<url2>,...
All other cluster nodes
--cluster_key <key>
Shared cluster key for identification
--election_timeout 5000
Raft election timeout
--heartbeat_timeout 1000
Raft leader heartbeat timeout
--wait_quorum_timeout 30000
Timeout for requests to wait for quorum to come up
--leader_priority <number>
Raft leader priority for this node (optional)
--stale_read 1
Allow to serve reads from followers. Specify 0 to disallow
--reconnect_interval 1000
Unavailable peer connection retry interval
--dump_timeout 5000
Timeout for dump command in milliseconds
--load_timeout 5000
Timeout for load command in milliseconds
--forward_timeout 1000
Timeout for forwarding requests from follower to leader in milliseconds
--replication_timeout 1000
Timeout for replicating requests from leader to follower in milliseconds
--compact_timeout 1000
Timeout for compaction requests from leader to follower in milliseconds
`;
function parse()
{
const options = { stale_read: 1 };
for (let i = 2; i < process.argv.length; i++)
{
const arg = process.argv[i].toLowerCase().replace(/^--(.+)$/, (m, m1) => '--'+m1.replace(/-/g, '_'));
if (arg === '-h' || arg === '--help')
{
process.stderr.write(help_text);
process.exit();
}
else if (arg.substr(0, 2) == '--')
{
options[arg.substr(2)] = process.argv[++i];
}
}
if (options['persist_filter'])
{
options['persist_filter'] = require(options['persist_filter'])(options);
}
return options;
}
const antietcd = new AntiEtcd(parse());
// Set exit hook
const on_stop_cb = async () => { await antietcd.stop(); process.exit(0); };
process.on('SIGINT', on_stop_cb);
process.on('SIGTERM', on_stop_cb);
process.on('SIGQUIT', on_stop_cb);
antietcd.start().catch(console.error);