##// END OF EJS Templates
fixed format-compile bug while formatting strings with new line symbols....
cin -
r15:d5a3d3ab9fd7 propose cancellat...
parent child
Show More
@@ -0,0 +1,39
1 import { IObservable, ICancellation, IDestroyable } from "@implab/core/interfaces";
2 import * as TraceEvent from '@implab/core/log/TraceEvent';
3 import { Cancellation } from "@implab/core/Cancellation";
4 import * as TraceSource from "@implab/core/log/TraceSource";
5 import * as tape from 'tape';
6 import { argumentNotNull } from "@implab/core/safe";
7
8 export class TapeWriter implements IDestroyable {
9 readonly _tape: tape.Test
10
11 _subscriptions = new Array<IDestroyable>();
12
13 constructor(tape: tape.Test) {
14 argumentNotNull(tape, "tape");
15 this._tape = tape;
16 }
17
18 writeEvents(source: IObservable<TraceEvent>, ct: ICancellation = Cancellation.none) {
19 let subscription = source.on(this.writeEvent.bind(this));
20 if (ct.isSupported()) {
21 ct.register(subscription.destroy.bind(subscription));
22 }
23 this._subscriptions.push(subscription);
24 }
25
26 writeEvent(next: TraceEvent) {
27 if (next.level >= TraceSource.LogLevel) {
28 this._tape.comment("LOG " + next.arg);
29 } else if(next.level >= TraceSource.WarnLevel) {
30 this._tape.comment("WARN " + next.arg);
31 } else {
32 this._tape.comment("ERROR " + next.arg);
33 }
34 }
35
36 destroy() {
37 this._subscriptions.forEach(x => x.destroy());
38 }
39 } No newline at end of file
@@ -133,7 +133,7
133 133 },
134 134 "minimist": {
135 135 "version": "0.0.5",
136 "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.5.tgz",
136 "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.5.tgz",
137 137 "integrity": "sha1-16oye87PUY+RBqxrjwA/o7zqhWY=",
138 138 "dev": true
139 139 },
@@ -319,9 +319,9
319 319 }
320 320 },
321 321 "requirejs": {
322 "version": "2.3.6",
323 "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz",
324 "integrity": "sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==",
322 "version": "2.3.5",
323 "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.5.tgz",
324 "integrity": "sha512-svnO+aNcR/an9Dpi44C7KSAy5fFGLtmPbaaCeQaklUz8BQhS64tWWIIlvEA5jrWICzlO/X9KSzSeXFnZdBu8nw==",
325 325 "dev": true
326 326 },
327 327 "resolve": {
@@ -413,9 +413,9
413 413 }
414 414 },
415 415 "typescript": {
416 "version": "3.0.3",
417 "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.0.3.tgz",
418 "integrity": "sha512-kk80vLW9iGtjMnIv11qyxLqZm20UklzuR2tL0QAnDIygIUIemcZMxlMWudl9OOt76H3ntVzcTiddQ1/pAAJMYg==",
416 "version": "2.9.2",
417 "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz",
418 "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==",
419 419 "dev": true
420 420 },
421 421 "wrappy": {
@@ -18,13 +18,13 define(
18 18 var espaceString = function(s) {
19 19 if (!s)
20 20 return s;
21 return "'" + s.replace(/('|\\)/g, "\\$1") + "'";
21 return "'" + s.replace(/('|\\)/g, "\\$1").replace("\n","\\n") + "'";
22 22 };
23 23
24 24 var encode = function(s) {
25 25 if (!s)
26 26 return s;
27 return s.replace(/\\{|\\}|&|\\:/g, function(m) {
27 return s.replace(/\\{|\\}|&|\\:|\n/g, function(m) {
28 28 return map[m] || m;
29 29 });
30 30 };
@@ -4,79 +4,162 import { argumentNotNull } from '../safe
4 4
5 5
6 6 interface Handler<T> {
7 (x:T) : void
7 (x: T): void
8 8 }
9 9
10 10 interface Initializer<T> {
11 (notify: Handler<T>) : (() => void) | void;
11 (notify: Handler<T>, error?: (e: any) => void, complete?: () => void): (() => void) | void;
12 12 }
13 13
14 // TODO: think about to move this interfaces.ts and make it public
15 interface IObserver<T> {
16 next(event: T): void
17
18 error(e: any): void
19
20 complete(): void
21 }
14 22
15 23 class Observable<T> implements IObservable<T>, IDestroyable {
16 private _once = new Array<Handler<T>>();
24 private _once = new Array<IObserver<T>>();
25
26 private _observers = new Array<IObserver<T>>();
17 27
18 private readonly _observers = new Array<Handler<T>>();
28 private _cleanup: (() => void) | void;
19 29
20 private readonly _cleanup : (() => void) | void;
30 private _complete: boolean
31
32 private _error: any
21 33
22 34 constructor(func?: Initializer<T>) {
23 this._cleanup = func && func(this._notify.bind(this));
35 this._cleanup = func && func(
36 this._notifyNext.bind(this),
37 this._notifyError.bind(this),
38 this._notifyCompleted.bind(this)
39 );
24 40 }
25 41
26 on(observer: Handler<T>, error?: Handler<any>, complete?: () => void): IDestroyable {
27 argumentNotNull(observer, "observer");
28
29 this._observers.push(observer);
42 /**
43 * Registers handlers for the current observable object.
44 *
45 * @param next the handler for events
46 * @param error the handler for a error
47 * @param complete the handler for a completion
48 * @returns {IDestroyable} the handler for the current subscription, this
49 * handler can be used to unsubscribe from events.
50 *
51 */
52 on(next: Handler<T>, error?: Handler<any>, complete?: () => void): IDestroyable {
53 argumentNotNull(next, "next");
30 54
31 55 let me = this;
32 return {
56
57 let observer: IObserver<T> & IDestroyable = {
58 next: next,
59
60 error(e: any) {
61 if (error)
62 error(e);
63 },
64
65 complete() {
66 if (complete)
67 complete();
68 },
69
33 70 destroy() {
34 me._removeObserver(observer);
71 me._removeObserver(this);
35 72 }
36 73 }
74
75 this._addObserver(observer);
76
77
78 return observer;
79 }
80
81 private _addObserver(observer: IObserver<T>) {
82 if (this._complete) {
83 try {
84 if (this._error)
85 observer.error(this._error);
86 else
87 observer.complete();
88 } catch (e) {
89 this.onObserverException(e);
90 }
91 } else {
92 this._observers.push(observer);
93 }
37 94 }
38 95
96 /**
97 * Waits for the next event. This method can't be used to read messages
98 * as a sequence since it can skip some messages between calls.
99 *
100 * @param ct a cancellation token
101 */
39 102 next(ct: ICancellation = Cancellation.none): Promise<T> {
40 103 return new Promise<T>((resolve, reject) => {
41 this._once.push(resolve);
42 if (ct.isSupported()) {
104 let observer: IObserver<T> = {
105 next: resolve,
106 error: reject,
107 complete: () => reject("No more events are available")
108 };
109
110 if (this._addOnce(observer) && ct.isSupported()) {
43 111 ct.register((e) => {
44 this._removeOnce(resolve);
112 this._removeOnce(observer);
45 113 reject(e);
46 114 });
47 115 }
48 116 });
49 117 }
50 118
119 private _addOnce(observer: IObserver<T>) {
120 if (this._complete) {
121 try {
122 if (this._error)
123 observer.error(this._error);
124 else
125 observer.complete();
126 } catch (e) {
127 this.onObserverException(e);
128 }
129 return false;
130 }
131
132 this._once.push(observer);
133 return true;
134 }
135
51 136 destroy() {
52 if(this._cleanup)
53 this._cleanup.call(null);
137 if (this._complete)
138 this._notifyCompleted();
139
140 let cleanup = this._cleanup;
141 if (cleanup) {
142 this._cleanup = null;
143 cleanup();
144 }
54 145 }
55 146
56 147 protected onObserverException(e: any) {
57 148 }
58 149
59 private _removeOnce(d: Handler<T>) {
150 private _removeOnce(d: IObserver<T>) {
60 151 let i = this._once.indexOf(d);
61 152 if (i >= 0)
62 153 this._once.splice(i);
63 154 }
64 155
65 private _removeObserver(d: Handler<T>) {
156 private _removeObserver(d: IObserver<T>) {
66 157 let i = this._observers.indexOf(d);
67 158 if (i >= 0)
68 159 this._observers.splice(i);
69 160 }
70 161
71 protected _notify(evt: T) {
72 let guard = (observer: Handler<T>) => {
73 try {
74 observer(evt);
75 } catch (e) {
76 this.onObserverException(e);
77 }
78 }
79
162 private _notify(guard: (observer: IObserver<T>) => void) {
80 163 if (this._once.length) {
81 164 for (let i = 0; i < this._once.length; i++)
82 165 guard(this._once[i]);
@@ -86,6 +169,44 class Observable<T> implements IObservab
86 169 for (let i = 0; i < this._observers.length; i++)
87 170 guard(this._observers[i]);
88 171 }
172
173 protected _notifyNext(evt: T) {
174 let guard = (observer: IObserver<T>) => {
175 try {
176 observer.next(evt);
177 } catch (e) {
178 this.onObserverException(e);
179 }
180 }
181
182 this._notify(guard);
183 }
184
185 protected _notifyError(e: any) {
186 let guard = (observer: IObserver<T>) => {
187 try {
188 observer.error(e);
189 } catch (e) {
190 this.onObserverException(e);
191 }
192 }
193
194 this._notify(guard);
195 this._observers = [];
196 }
197
198 protected _notifyCompleted() {
199 let guard = (observer: IObserver<T>) => {
200 try {
201 observer.complete();
202 } catch (e) {
203 this.onObserverException(e);
204 }
205 }
206
207 this._notify(guard);
208 this._observers = [];
209 }
89 210 }
90 211
91 212 namespace Observable {
@@ -67,7 +67,7 class TraceSource extends Observable<Tra
67 67 }
68 68
69 69 protected emit(level: number, arg: any) {
70 this._notify(new TraceEvent(this, level, arg));
70 this._notifyNext(new TraceEvent(this, level, arg));
71 71 }
72 72
73 73 isDebugEnabled() {
@@ -1,25 +1,31
1 import { IObservable } from "../../interfaces";
1 import { IObservable, IDestroyable, ICancellation } from "../../interfaces";
2 2 import * as TraceEvent from '../TraceEvent';
3 import { ICancellation } from "../../interfaces";
4 3 import { Cancellation } from "../../Cancellation";
5 4 import * as TraceSource from "../TraceSource";
6 5
7 class ConsoleWriter {
8 async write(source: IObservable<TraceEvent>, ct: ICancellation = Cancellation.none) {
9 let next;
10 while(next = await source.next(ct)) {
11 this._writeEvent(next);
6 class ConsoleWriter implements IDestroyable {
7 readonly _subscriptions = new Array<IDestroyable>();
8
9 writeEvents(source: IObservable<TraceEvent>, ct: ICancellation = Cancellation.none) {
10 var subscription = source.on(this.writeEvent.bind(this));
11 if (ct.isSupported()) {
12 ct.register(subscription.destroy.bind(subscription));
13 }
14 this._subscriptions.push(subscription);
15 }
16
17 writeEvent(next: TraceEvent) {
18 if (next.level >= TraceSource.LogLevel) {
19 console.log(next.source.id.toString(), next.arg);
20 } else if(next.level >= TraceSource.WarnLevel) {
21 console.warn(next.source.id.toString(), next.arg);
22 } else {
23 console.error(next.source.id.toString(), next.arg);
12 24 }
13 25 }
14 26
15 private _writeEvent(next: TraceEvent) {
16 if (next.level >= TraceSource.LogLevel) {
17 console.log(next.source.toString(), next.arg);
18 } else if(next.level >= TraceSource.WarnLevel) {
19 console.warn(next.source.toString(), next.arg);
20 } else {
21 console.error(next.source.toString(), next.arg);
22 }
27 destroy() {
28 this._subscriptions.forEach(x => x.destroy());
23 29 }
24 30 }
25 31
@@ -1,6 +1,7
1 1 import * as TraceSource from '@implab/core/log/TraceSource'
2 2 import * as tape from 'tape';
3 3 import * as ConsoleWriter from '@implab/core/log/writers/ConsoleWriter';
4 import { TapeWriter } from './TestTraits';
4 5
5 6 const sourceId = 'test/TraceSourceTests';
6 7
@@ -44,19 +45,26 tape('trace event', t => {
44 45 h.destroy();
45 46 });
46 47
47 tape('console writer', async t => {
48 let writer = new ConsoleWriter();
48 tape('tape comment writer', async t => {
49 let writer = new TapeWriter(t);
50
51 TraceSource.on(ts => {
52 writer.writeEvents(ts);
53 });
49 54
50 55 let trace = TraceSource.get(sourceId);
51 56 trace.level = TraceSource.DebugLevel;
52 57
53 let p = writer.write(trace);
54
55 58 trace.log("Hello, {0}!", 'World');
59 trace.log("Multi\n line");
56 60 trace.warn("Look at me!");
57 61 trace.error("DIE!");
58 62
59 console.log("DONE");
63 writer.destroy();
64
65 trace.log("You shouldn't see it!");
66
67 t.comment("DONE");
60 68
61 69 t.end();
62 70 }); No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now