Skip to content

Commit

Permalink
Restructures files
Browse files Browse the repository at this point in the history
  • Loading branch information
godu committed May 4, 2016
1 parent ee16fd9 commit 9e43248
Show file tree
Hide file tree
Showing 21 changed files with 289 additions and 63 deletions.
143 changes: 143 additions & 0 deletions MARBLE.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# Marble

## Fallback

On init, if a `fallback` file is specified, squirrel load content as first state. Allows restart without an available ETCD cluster.

- If `fallback` is specified

```
-A|
```

A is the content of fallback file wrapped in `GET` action.

```JSON
{
"action": "GET",
"node": {
"key": "/",
"dir": true,
"nodes": []
}
}
```

- If `fallback` isn't specified

```
|
```

- If `fallback` file doesn't exists

```
|
```

## Fetcher

On init, squirrel fetch ETCD until success.

```
-A|
```

A is the content of ETCD wrapped in `GET` action.

```JSON
{
"action": "GET",
"node": {
"key": "/",
"dir": true,
"nodes": []
}
}
```

On error, retry until is success.

## Watcher

Watch modification on ETCD cluster.

```
-A-B-C-
```

A B C are actions.

`SET` action:
```JSON
{
"action": "set",
"node": {
"key": "/foo",
"value": "foo",
"modifiedIndex": 1438,
"createdIndex": 1438
},
"prevNode": {
"key": "/foo",
"value": "bar",
"modifiedIndex": 1437,
"createdIndex": 1437
}
}
```

`DELETE` action:
```JSON
{
"action": "delete",
"node": {
"key": "/foo",
"modifiedIndex": 1435,
"createdIndex": 1434
},
"prevNode": {
"key": "/foo",
"value": "bar",
"modifiedIndex": 1434,
"createdIndex": 1434
}
}
```

`RESYNC` action (server cleared and outdated the index)
```JSON
{
"action": "resync"
}
```

## ETCD

Combine `fallback`, `fetcher` and `watcher` observable.

```
-A| // fallback
-B| // fetcher
--C-D-E- // watcher
-ABC-D-E-
```

## Combiner

Aggregate ETCD's events to rebuild representation of ETCD content.

```
-a-b-c- // ETCD's events
------
\ \ \
A \ C
B
-A---BC // ConcatAll
```

A & C are `SET` or `GET` events.
B is a `RESYNC` event which is tranform to `fetch` observable.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,9 @@ $ npm test
```

Please note that test use an actual etcd service




## [Marble](./MARBLE.md)

File renamed without changes.
4 changes: 2 additions & 2 deletions src/combiner.js → src/combine.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {set, del} from './patcher';
import {set, del} from './patch';
import createDebug from 'debug';
const debug = createDebug('squirrel:combiner');
const debug = createDebug('squirrel:combine');

const createCombiner$ = event$ => {
return event$.scan((store, action) => {
Expand Down
45 changes: 5 additions & 40 deletions src/etcd.js
Original file line number Diff line number Diff line change
@@ -1,47 +1,12 @@
import {Observable} from 'rxjs';
import {parseAction} from './parser';
import createDebug from 'debug';
const debug = createDebug('squirrel:etcd');

const createFetch$ = (client, cwd) => {
debug(`fetch: ${cwd}`);
const list = Observable.bindNodeCallback(
cb => client.get(cwd, {recursive: true}, (err, data) => cb(err, data))
);

return Observable.of(1)
.flatMap(() => list())
.retry(Infinity)
.map(parseAction);
};

const createWatcher$ = watcher => {
const set$ = Observable.fromEvent(watcher, 'set');
const delete$ = Observable.fromEvent(watcher, 'delete');
const reSync$ = Observable.fromEvent(watcher, 'resync');

return Observable.merge(set$, delete$, reSync$)
.map(parseAction);
};
import createWatcher$ from './watch';
import createResync$ from './resync';

const createEtcd$ = (client, watcher, cwd) => {
const watcher$ = createWatcher$(watcher);

const events$ = watcher$.startWith({
const events$ = createWatcher$(watcher).startWith({
action: 'resync'
}).flatMap(action => {
if (action.action === 'resync') {
debug('watcher: resync');
return createFetch$(client, cwd);
}
return Observable.of(action);
});

return events$;
return createResync$(client, cwd, events$);
};

export {
createFetch$,
createWatcher$,
createEtcd$
};
export default createEtcd$;
2 changes: 1 addition & 1 deletion src/fallback.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {readFile} from 'fs';
import {isString, identity} from 'lodash/fp';
import {Observable} from 'rxjs';
import {parseAction} from './parser';
import {parseAction} from './parse';
import createDebug from 'debug';
const debug = createDebug('squirrel:fallback');

Expand Down
18 changes: 18 additions & 0 deletions src/fetch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {Observable} from 'rxjs';
import {parseAction} from './parse';
import createDebug from 'debug';
const debug = createDebug('squirrel:etcd');

const createFetch$ = (client, cwd) => {
debug(`fetch: ${cwd}`);
const list = Observable.bindNodeCallback(
cb => client.get(cwd, {recursive: true}, (err, data) => cb(err, data))
);

return Observable.of(1)
.flatMap(() => list())
.retry(Infinity)
.map(parseAction);
};

export default createFetch$;
10 changes: 5 additions & 5 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import Etcd from 'node-etcd';
import {Observable} from 'rxjs';
import createDebug from 'debug';

import {createEtcd$} from './etcd';
import createEtcd$ from './etcd';
import createFallback$ from './fallback';
import createCombiner$ from './combiner';
import createCombiner$ from './combine';
import createStore from './store';
import createAPI from './api';
import createSave from './save';
import createIndexer from './indexer';
import createIndexBuilder from './build-index';

const debug = createDebug('squirrel');

Expand All @@ -34,7 +34,7 @@ const createSquirrel = options => {

const client = new Etcd(options.hosts, pick(['auth', 'ca', 'key', 'cert'], options));
const watcher = client.watcher(options.cwd, null, {recursive: true});
const indexer = createIndexer(options.indexes);
const indexBuilder = createIndexBuilder(options.indexes);
const save = options.save ? createSave(options.fallback) : identity;

const events$ = Observable.concat(
Expand All @@ -45,7 +45,7 @@ const createSquirrel = options => {
const node$ = createCombiner$(events$);
const {store, observable} = createStore(
save(node$),
indexer
indexBuilder
);
const api = createAPI(store);

Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion src/patcher.js → src/patch.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
startsWith
} from 'lodash/fp';
import createDebug from 'debug';
const debug = createDebug('squirrel:patcher');
const debug = createDebug('squirrel:patch');

const get = (store, {action, node}) => {
if (!startsWith(store.key, node.key)) return null;
Expand Down
15 changes: 15 additions & 0 deletions src/resync.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import {Observable} from 'rxjs';
import createFetcher$ from './fetch';
import createDebug from 'debug';
const debug = createDebug('squirrel:etcd');

const createResync$ = (client, cwd, events$) =>
events$.flatMap(action => {
if (action.action === 'resync') {
debug('watcher: resync');
return createFetcher$(client, cwd);
}
return Observable.of(action);
});

export default createResync$;
10 changes: 5 additions & 5 deletions src/test/indexer.js → src/test/build-index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import test from 'ava';
import createIndexer from '../indexer';
import createIndexBuild from '../build-index';

test('should create indexer', t => {
createIndexer(['name']);
createIndexBuild(['name']);
});

test('should create index', t => {
Expand Down Expand Up @@ -41,7 +41,7 @@ test('should create index', t => {
}
};

t.deepEqual(createIndexer(indexes)(input), output);
t.deepEqual(createIndexBuild(indexes)(input), output);
});

test('should index with two same entry', t => {
Expand Down Expand Up @@ -74,7 +74,7 @@ test('should index with two same entry', t => {
}
};

t.deepEqual(createIndexer(indexes)(input), output);
t.deepEqual(createIndexBuild(indexes)(input), output);
});

test('should create index with deep key', t => {
Expand Down Expand Up @@ -121,5 +121,5 @@ test('should create index with deep key', t => {
}
};

t.deepEqual(createIndexer(indexes)(input), output);
t.deepEqual(createIndexBuild(indexes)(input), output);
});
4 changes: 2 additions & 2 deletions src/test/combiner.js → src/test/combine.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {Observable} from 'rxjs';
import test from 'ava';
import {Observable} from 'rxjs';

import createCombiner$ from '../combiner';
import createCombiner$ from '../combine';

import emptyRoot from './fixtures/empty-root';
import setEvent from './fixtures/set-event';
Expand Down
4 changes: 2 additions & 2 deletions src/test/etcd.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import test from 'ava';

import createEtcd from './helpers/etcd';
import {createEtcd$} from '../etcd';
import createEtcd$ from '../etcd';

import setEvent from './fixtures/set-event';
import deleteEvent from './fixtures/delete-event';
import resyncEvent from './fixtures/resync-event';

test('should resync', async t => {
test('should composite events observable', async t => {
const client = createEtcd({
get: [[null, {
action: 'get',
Expand Down
2 changes: 1 addition & 1 deletion src/test/fallback.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import test from 'ava';
import {join} from 'path';
import {parseNode} from '../parser';
import {parseNode} from '../parse';

import createFallback$ from '../fallback';

Expand Down
2 changes: 1 addition & 1 deletion src/test/fetch.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import test from 'ava';
import {pipe, fill, map, concat} from 'lodash/fp';

import createEtcd from './helpers/etcd';
import {createFetch$} from '../etcd';
import createFetch$ from '../fetch';

import emptyRoot from './fixtures/empty-root';

Expand Down
2 changes: 1 addition & 1 deletion src/test/parser.js → src/test/parse.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import test from 'ava';
import {parseAction, parseNode} from '../parser';
import {parseAction, parseNode} from '../parse';

test('should parseNode', t => {
const tests = [{
Expand Down
2 changes: 1 addition & 1 deletion src/test/patcher.js → src/test/patch.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import test from 'ava';
import {get, set, del} from '../patcher';
import {get, set, del} from '../patch';

test('should get node', t => {
const input = {
Expand Down

0 comments on commit 9e43248

Please sign in to comment.