Kaynağa Gözat

Introduced the `ContextWatchdog#itemRestart` and `ContextWatchdog#itemError` events.

Maciej Bukowski 6 yıl önce
ebeveyn
işleme
557007aea8

+ 13 - 3
packages/ckeditor5-watchdog/docs/features/watchdog.md

@@ -255,13 +255,23 @@ const editor1State = watchdog.getState( 'editor1' );
 // Getting the context state.
 const contextState = watchdog.state;
 
-// Listening to an event fired when the context watchdog catches the context-related error.
+// The `error` event is fired when the context watchdog catches the context-related error.
 // Note that the item errors are not re-fired in the `ContextWatchdog#error`.
-watchdog.on( 'error', () => {} );
+watchdog.on( 'error', ( evt, { error } ) => {} );
 
-// Listening to an event fired when the context is set back to the `ready` state (after it was in `error` state).
+// The `restarted` event is fired when the context is set back to the `ready` state (after it was in `error` state).
 // Similarly, this event is not thrown for internal item restarts.
 watchdog.on( 'restart', () => {} );
+
+// The `itemError` event is fired when an error occurred in one of the added items
+watchdog.on( 'itemError', ( evt, { error, itemId } ) => {
+	console.log( `An error occurred in the item with the '${ itemId }' id.` );
+} );
+
+// The `itemRestarted` event is fired when the item is set back to the `ready` state (after it was in `error` state).
+watchdog.on( 'itemRestart', ( evt, { itemId } ) => {
+	console.log( 'The item with with the '${ itemId }' id has been restarted.' );
+} );
 ```
 
 ## Configuration

+ 15 - 5
packages/ckeditor5-watchdog/src/contextwatchdog.js

@@ -266,12 +266,22 @@ export default class ContextWatchdog extends Watchdog {
 					this._watchdogs.set( item.id, watchdog );
 
 					// Enqueue the internal watchdog errors within the main queue.
-					watchdog.on( 'error', () => {
-						if ( watchdog._shouldRestart() ) {
-							this._actionQueue.enqueue( () => new Promise( res => {
-								watchdog.once( 'restart', () => res() );
-							} ) );
+					// And propagate the internal `error` events as `itemError` event.
+					watchdog.on( 'error', ( evt, { error, causesRestart } ) => {
+						this.fire( 'itemError', { itemId: item.id, error } );
+
+						// Do not enqueue the item restart action if the item will not restart.
+						if ( !causesRestart ) {
+							return;
 						}
+
+						this._actionQueue.enqueue( () => new Promise( res => {
+							watchdog.once( 'restart', () => {
+								this.fire( 'itemRestart', { itemId: item.id } );
+
+								res();
+							} );
+						} ) );
 					} );
 
 					return watchdog.create( item.sourceElementOrData, item.config, this._context );

+ 4 - 2
packages/ckeditor5-watchdog/src/watchdog.js

@@ -219,10 +219,12 @@ export default class Watchdog {
 				date: this._now()
 			} );
 
-			this.fire( 'error', { error } );
+			const causesRestart = this._shouldRestart();
+
+			this.fire( 'error', { error, causesRestart } );
 			this.state = 'crashed';
 
-			if ( this._shouldRestart() ) {
+			if ( causesRestart ) {
 				this._restart();
 			} else {
 				this.state = 'crashedPermanently';

+ 58 - 0
packages/ckeditor5-watchdog/tests/contextwatchdog.js

@@ -564,6 +564,64 @@ describe( 'ContextWatchdog', () => {
 
 				await watchdog.destroy();
 			} );
+
+			it( 'should rethrow item `error` events as `itemError` events', async () => {
+				watchdog = new ContextWatchdog( Context );
+
+				watchdog.create();
+
+				await watchdog.add( [ {
+					id: 'editor1',
+					type: 'editor',
+					creator: ( el, config ) => ClassicTestEditor.create( el, config ),
+					sourceElementOrData: element1,
+					config: {}
+				} ] );
+
+				const itemErrorSpy = sinon.spy();
+
+				watchdog.on( 'itemError', itemErrorSpy );
+
+				setTimeout( () => throwCKEditorError( 'foo', watchdog.get( 'editor1' ) ) );
+
+				await waitCycle();
+
+				sinon.assert.calledOnce( itemErrorSpy );
+				sinon.assert.calledWith( itemErrorSpy, sinon.match.any, sinon.match( data => {
+					return data.itemId === 'editor1';
+				} ) );
+
+				await watchdog.destroy();
+			} );
+
+			it( 'should rethrow item `restart` events as `itemRestart` events', async () => {
+				watchdog = new ContextWatchdog( Context );
+
+				watchdog.create();
+
+				await watchdog.add( [ {
+					id: 'editor1',
+					type: 'editor',
+					creator: ( el, config ) => ClassicTestEditor.create( el, config ),
+					sourceElementOrData: element1,
+					config: {}
+				} ] );
+
+				const itemRestartSpy = sinon.spy();
+
+				watchdog.on( 'itemRestart', itemRestartSpy );
+
+				setTimeout( () => throwCKEditorError( 'foo', watchdog.get( 'editor1' ) ) );
+
+				await waitCycle();
+
+				sinon.assert.calledOnce( itemRestartSpy );
+				sinon.assert.calledWith( itemRestartSpy, sinon.match.any, sinon.match( data => {
+					return data.itemId === 'editor1';
+				} ) );
+
+				await watchdog.destroy();
+			} );
 		} );
 	} );
 } );