From 0028d591fa001d0fcb42316f334149ae79dde237 Mon Sep 17 00:00:00 2001 From: Tobias Laundal Date: Wed, 17 Aug 2022 14:09:23 +0200 Subject: [PATCH 1/2] feat!: remove all marker functionality The marker functionality was introduced to support building a tree of streams, in effect determining how different observables relate to eachother without needing to watch values pass through. This was never used to its full potential. The effect on the codebase of RxBeach and all users is quite big, as it means we need to reexport decorated versions of operators from RxJS. BREAKING CHANGE: RxBeach no longer re-exports operators from RxJS. These operators must now be imported directly from RxJS. --- src/action$.ts | 3 +- src/actionCreator.ts | 2 - src/decoratedObservableCombiners.spec.ts | 110 ------------ src/decoratedObservableCombiners.ts | 14 -- src/derivedStream.spec.ts | 35 ---- src/derivedStream.ts | 9 +- src/index.ts | 2 - src/internal/index.ts | 14 -- src/internal/markers.spec.ts | 149 ---------------- src/internal/markers.ts | 206 ----------------------- src/internal/types.ts | 2 - src/namespace.spec.ts | 2 - src/operators/decorated.spec.ts | 139 --------------- src/operators/decorated.ts | 52 ------ src/operators/index.ts | 7 - src/operators/operators.spec.ts | 27 +-- src/operators/operators.ts | 6 +- src/operators/reduceState.ts | 2 - src/persistentReducedStream.ts | 4 +- 19 files changed, 8 insertions(+), 777 deletions(-) delete mode 100644 src/decoratedObservableCombiners.spec.ts delete mode 100644 src/decoratedObservableCombiners.ts delete mode 100644 src/internal/markers.spec.ts delete mode 100644 src/internal/markers.ts delete mode 100644 src/operators/decorated.spec.ts delete mode 100644 src/operators/decorated.ts diff --git a/src/action$.ts b/src/action$.ts index 15da79d9..ad4f5bfa 100644 --- a/src/action$.ts +++ b/src/action$.ts @@ -1,5 +1,5 @@ import { Subject } from 'rxjs'; -import { UnknownAction, markName } from './internal'; +import { UnknownAction } from './internal'; import { ActionDispatcher, ActionStream } from './types/helpers'; import { tag } from 'rxjs-spy/operators'; import { share } from 'rxjs/operators'; @@ -12,7 +12,6 @@ const actionSubject$ = new Subject(); */ export const action$: ActionStream = actionSubject$.pipe( tag('action$'), - markName('action$'), share() ); diff --git a/src/actionCreator.ts b/src/actionCreator.ts index 1742bc1c..8cf6b738 100644 --- a/src/actionCreator.ts +++ b/src/actionCreator.ts @@ -2,7 +2,6 @@ import { ActionCreatorWithPayload, ActionCreatorWithoutPayload, } from './types/ActionCreator'; -import { actionMarker } from './internal/markers'; type ActionName = `[${string}] ${string}`; @@ -42,7 +41,6 @@ export const actionCreator: ActionCreatorFunc = (type: string) => { meta: Object.freeze({}), }); actionCreatorFn.type = type; - actionCreatorFn._marker = actionMarker(type); return Object.freeze(actionCreatorFn); }; diff --git a/src/decoratedObservableCombiners.spec.ts b/src/decoratedObservableCombiners.spec.ts deleted file mode 100644 index b9267104..00000000 --- a/src/decoratedObservableCombiners.spec.ts +++ /dev/null @@ -1,110 +0,0 @@ -import test from 'ava'; -import { Observable } from 'rxjs'; -import { - MarkerType, - NameMarker, - findMarker, - markName, -} from './internal/markers'; -import { combineLatest, merge, zip } from './decoratedObservableCombiners'; -import { marbles } from 'rxjs-marbles/ava'; - -const source$ = new Observable().pipe(markName('source')); -const dependency1$ = source$.pipe(markName('dependency1')); -const dependency2$ = source$.pipe(markName('dependency2')); - -const source: NameMarker = { - type: MarkerType.NAME, - name: 'source', - sources: [null], -}; -const dependency1: NameMarker = { - type: MarkerType.NAME, - name: 'dependency1', - sources: [source], -}; -const dependency2: NameMarker = { - type: MarkerType.NAME, - name: 'dependency2', - sources: [source], -}; - -const letters = { a: 'A', b: 'B', c: 'C', d: 'D' }; -const combined = { - B: ['A', 'B'] as [string, string], - C: ['C', 'B'] as [string, string], - D: ['C', 'D'] as [string, string], -}; - -test('merge adds name and merge marker', (t) => { - const merged$ = merge(source$, dependency1$, dependency2$); - - t.deepEqual(findMarker(merged$), { - type: MarkerType.MERGE, - sources: [source, dependency1, dependency2], - }); -}); - -test( - 'merge emits for each emit from source', - marbles((m) => { - const alpha$ = m.hot(' a-c', letters); - const bravo$ = m.hot(' -b-', letters); - const merged$ = m.hot('abc', letters); - - m.expect(merge(alpha$, bravo$)).toBeObservable(merged$); - }) -); - -test('zip adds name and combine marker', (t) => { - const derived$ = zip(source$, dependency1$, dependency2$); - - t.deepEqual(findMarker(derived$), { - type: MarkerType.ZIP, - sources: [source, dependency1, dependency2], - }); -}); - -test( - 'zip emits on emit from sources', - marbles((m) => { - const alpha$ = m.hot(' a-c-', letters); - const bravo$ = m.hot(' -b-d', letters); - const combined$ = m.hot('-B-D', combined); - - m.expect(zip(alpha$, bravo$)).toBeObservable(combined$); - }) -); - -test('combineLatest adds name and merge marker', (t) => { - const combined$ = combineLatest(source$, dependency1$, dependency2$); - - t.deepEqual(findMarker(combined$), { - type: MarkerType.COMBINE_LATEST, - sources: [source, dependency1, dependency2], - }); -}); - -test( - 'combineLatest emits for each emit from source', - marbles((m) => { - const alpha$ = m.hot(' a-c', letters); - const bravo$ = m.hot(' -b-', letters); - const combined$ = m.hot('-BC', combined); - - m.expect(combineLatest(alpha$, bravo$)).toBeObservable(combined$); - }) -); - -test( - 'combineLatest supports a projection function', - marbles((m) => { - const alpha$ = m.hot('a-c', letters); - const bravo$ = m.hot('-b-', letters); - const combined$ = m.hot('-bb', letters); - - m.expect(combineLatest(alpha$, bravo$, (_, b) => b)).toBeObservable( - combined$ - ); - }) -); diff --git a/src/decoratedObservableCombiners.ts b/src/decoratedObservableCombiners.ts deleted file mode 100644 index 5770d872..00000000 --- a/src/decoratedObservableCombiners.ts +++ /dev/null @@ -1,14 +0,0 @@ -import * as rxjs from 'rxjs'; -import { Observable } from 'rxjs'; -import { markCombineLatest, markMerge, markZip } from './internal/markers'; - -export const combineLatest = ((...sources: Observable[]) => - rxjs - .combineLatest(...sources) - .pipe(markCombineLatest(sources))) as typeof rxjs.combineLatest; - -export const merge = ((...sources: Observable[]) => - rxjs.merge(...sources).pipe(markMerge(sources))) as typeof rxjs.merge; - -export const zip = ((...sources: Observable[]) => - rxjs.zip(...sources).pipe(markZip(sources))) as typeof rxjs.zip; diff --git a/src/derivedStream.spec.ts b/src/derivedStream.spec.ts index b5c6a3f5..79e1786b 100644 --- a/src/derivedStream.spec.ts +++ b/src/derivedStream.spec.ts @@ -1,42 +1,7 @@ import test from 'ava'; -import { - MarkerType, - NameMarker, - findMarker, - markName, -} from './internal/markers'; -import { Observable } from 'rxjs'; import { derivedStream } from './derivedStream'; import { marbles } from 'rxjs-marbles/ava'; -test('derivedStream adds name and combine marker', (t) => { - const source$ = new Observable().pipe(markName('source')); - const dependency$ = source$.pipe(markName('dependency')); - - const derived$ = derivedStream('derived', source$, dependency$); - - const sourceNameMarker: NameMarker = { - type: MarkerType.NAME, - name: 'source', - sources: [null], - }; - const dependencyNameMarker: NameMarker = { - type: MarkerType.NAME, - name: 'dependency', - sources: [sourceNameMarker], - }; - t.deepEqual(findMarker(derived$), { - type: MarkerType.NAME, - name: 'derived', - sources: [ - { - type: MarkerType.COMBINE_LATEST, - sources: [sourceNameMarker, dependencyNameMarker], - }, - ], - }); -}); - test( 'derivedStream emits on emit from either source', marbles((m) => { diff --git a/src/derivedStream.ts b/src/derivedStream.ts index 8d5b9d5a..f2d69986 100644 --- a/src/derivedStream.ts +++ b/src/derivedStream.ts @@ -1,6 +1,5 @@ -import { Observable, ObservableInput } from 'rxjs'; -import { combineLatest } from './decoratedObservableCombiners'; -import { markName } from './internal/markers'; +import { Observable, ObservableInput, combineLatest } from 'rxjs'; +import { tag } from 'rxjs-spy/operators'; export type DerivedStream = { (name: string, a: ObservableInput): Observable<[A]>; @@ -95,7 +94,7 @@ export type DerivedStream = { * Make this stream a derived stream of its source and dependencies * * This is basically an annotated version of the `combineLatest` operator that - * adds markers so the stream can be analyzed. + * adds tags so the stream can be analyzed. * * @param name The unique name of this stream * @param dependencies The dependencies of this stream @@ -104,4 +103,4 @@ export type DerivedStream = { export const derivedStream: DerivedStream = ( name: string, ...dependencies: ObservableInput[] -): Observable => combineLatest(...dependencies).pipe(markName(name)); +): Observable => combineLatest(dependencies).pipe(tag(name)); diff --git a/src/index.ts b/src/index.ts index 195383f0..684ca985 100644 --- a/src/index.ts +++ b/src/index.ts @@ -36,8 +36,6 @@ export { export { derivedStream } from './derivedStream'; -export { combineLatest, merge, zip } from './decoratedObservableCombiners'; - export { persistentReducedStream } from './persistentReducedStream'; export { ObservableState } from './observableState'; diff --git a/src/internal/index.ts b/src/internal/index.ts index f61ca19f..14b37a48 100644 --- a/src/internal/index.ts +++ b/src/internal/index.ts @@ -9,17 +9,3 @@ export { RoutineFunc } from './routineFunc'; export { coldMergeOperators } from '../operators/mergeOperators'; export { defaultErrorSubject } from './defaultErrorSubject'; export { rethrowErrorGlobally } from './rethrowErrorGlobally'; -export { - actionMarker, - markName, - markOfType, - markCombineLatest, - markWithLatestFrom, - markMerge, - markZip, - MarkedObservable, - findMarker, - Marker, - MarkerInterface, - MarkerType, -} from './markers'; diff --git a/src/internal/markers.spec.ts b/src/internal/markers.spec.ts deleted file mode 100644 index 9583c068..00000000 --- a/src/internal/markers.spec.ts +++ /dev/null @@ -1,149 +0,0 @@ -import test, { Macro } from 'ava'; -import { Observable, OperatorFunction, empty, noop, pipe } from 'rxjs'; -import { - MarkerType, - NameMarker, - actionMarker, - findMarker, - markCombineLatest, - markDebounceTime, - markMerge, - markName, - markOfType, - markWithLatestFrom, - markZip, -} from './markers'; -import { - catchError, - filter, - map, - pluck, - scan, - shareReplay, - tap, -} from 'rxjs/operators'; - -const source$ = new Observable().pipe(markName('source')); -const dependency$ = source$.pipe(markName('dependency')); -const TOP_MARKER: NameMarker = { - type: MarkerType.NAME, - name: 'source', - sources: [null], -}; -const dependency: NameMarker = { - type: MarkerType.NAME, - name: 'dependency', - sources: [TOP_MARKER], -}; - -test('actionMarker creates actionMarker', (t) => { - t.deepEqual(actionMarker('heyo'), { - type: MarkerType.ACTION, - name: 'heyo', - }); -}); - -test('markName marks name', (t) => { - t.deepEqual(findMarker(source$), TOP_MARKER); -}); - -test('markName includes parent marker', (t) => { - const piped$ = source$.pipe(markName('piped')); - - t.deepEqual(findMarker(piped$), { - type: MarkerType.NAME, - name: 'piped', - sources: [TOP_MARKER], - }); -}); - -test('markOfType marks action dependencies', (t) => { - const piped$ = source$.pipe( - markOfType([actionMarker('alpha'), actionMarker('bravo')]) - ); - - t.deepEqual(findMarker(piped$), { - type: MarkerType.OF_TYPE, - sources: [ - { - type: MarkerType.ACTION, - name: 'alpha', - }, - { - type: MarkerType.ACTION, - name: 'bravo', - }, - ], - }); -}); - -test('markCombineLatest includes sources', (t) => { - const alpha$ = source$.pipe(markName('alpha')); - const piped$ = source$.pipe(markCombineLatest([alpha$, dependency$])); - - t.deepEqual(findMarker(piped$), { - type: MarkerType.COMBINE_LATEST, - sources: [ - { - type: MarkerType.NAME, - name: 'alpha', - sources: [TOP_MARKER], - }, - dependency, - ], - }); -}); - -test('markWithLatestFrom includes source and dependencies', (t) => { - const piped$ = source$.pipe(markWithLatestFrom(source$, [dependency$])); - - t.deepEqual(findMarker(piped$), { - type: MarkerType.WITH_LATEST_FROM, - sources: [TOP_MARKER], - dependencies: [dependency], - }); -}); - -test('markMerge includes sources', (t) => { - const piped$ = source$.pipe(markMerge([source$, dependency$])); - - t.deepEqual(findMarker(piped$), { - type: MarkerType.MERGE, - sources: [TOP_MARKER, dependency], - }); -}); - -test('markZip includes sources', (t) => { - const piped$ = source$.pipe(markZip([source$, dependency$])); - - t.deepEqual(findMarker(piped$), { - type: MarkerType.ZIP, - sources: [TOP_MARKER, dependency], - }); -}); - -test('markDebounceTime includes source', (t) => { - const piped$ = source$.pipe(markDebounceTime(source$, 0)); - - t.deepEqual(findMarker(piped$), { - type: MarkerType.DEBOUNCE_TIME, - sources: [TOP_MARKER], - time: 0, - }); -}); - -const findMarkerOver: Macro<[OperatorFunction]> = { - exec: (t, operator) => - t.deepEqual(findMarker(source$.pipe(operator)), TOP_MARKER), - title: (name) => `findMarker finds marker over ${name} operator`, -}; -const coop = () => true; -const emop = () => empty(); -test('filter', findMarkerOver, filter(coop)); -test('scan', findMarkerOver, scan(coop)); -test('shareReplay', findMarkerOver, shareReplay()); -test('catchError', findMarkerOver, catchError(emop)); -test('tap and map', findMarkerOver, pipe(tap(coop), map(coop))); -test('tap', findMarkerOver, tap(noop)); -test('map', findMarkerOver, map(coop)); -test('pluck', findMarkerOver, pluck('key')); diff --git a/src/internal/markers.ts b/src/internal/markers.ts deleted file mode 100644 index b9585c30..00000000 --- a/src/internal/markers.ts +++ /dev/null @@ -1,206 +0,0 @@ -import { MonoTypeOperatorFunction, Observable, ObservableInput } from 'rxjs'; - -export enum MarkerType { - NAME, - ACTION, - OF_TYPE, - COMBINE_LATEST, - WITH_LATEST_FROM, - MERGE, - ZIP, - DEBOUNCE_TIME, - INVALID, // For test use -} - -export type MarkerInterface = { - /** - * Type of the marker - */ - readonly type: MarkerType; - /** - * The name of the stream - * - * Should be unique, and human readable. - */ - readonly name?: string; - /** - * The streams that make this stream emit. - * - * `null` signifies streams without markers. - */ - readonly sources?: (Marker | null)[]; - /** - * Other streams this stream retrieves data from, but which does not trigger - * this stream to emit. - */ - readonly dependencies?: (Marker | null)[]; -}; - -type MarkerBase = { - readonly type: M; -}; - -/** - * A marker to name a stream - */ -export type NameMarker = MarkerBase & { - readonly name: string; - readonly sources: [Marker | null]; -}; - -/** - * A marker representing an action creator - */ -export type ActionMarker = MarkerBase & { - readonly name: string; -}; - -/** - * A marker for the `ofType` operator - */ -export type OfTypeMarker = MarkerBase & { - readonly sources: ActionMarker[]; -}; - -/** - * A marker for the `combineLatest` operator - */ -export type CombineLatestMarker = MarkerBase & { - readonly sources: (Marker | null)[]; -}; - -/** - * A marker for the `withLatestFrom` operator - */ -export type WithLatestFromMarker = MarkerBase & { - readonly sources: [Marker | null]; - readonly dependencies: (Marker | null)[]; -}; - -export type MergeMarker = MarkerBase & { - readonly sources: (Marker | null)[]; -}; - -export type ZipMarker = MarkerBase & { - readonly sources: (Marker | null)[]; -}; - -export type DebounceTimeMarker = MarkerBase & { - readonly sources: [Marker | null]; - readonly time: number; -}; - -export type Marker = - | NameMarker - | ActionMarker - | OfTypeMarker - | CombineLatestMarker - | WithLatestFromMarker - | MergeMarker - | ZipMarker - | DebounceTimeMarker; - -export const actionMarker = (name: string): ActionMarker => ({ - type: MarkerType.ACTION, - name, -}); - -/** - * An Observable with a marker field - * - * The Observable does not have it's own subscription function. Instead - * subscription is defered to the source. This means the marker is only visible - * when inspecting the Observable, and that it does not add extra function calls - * when subscribed. - */ -export class MarkedObservable extends Observable { - readonly marker: M; - - constructor(source: Observable, marker: M) { - // When the observable has no subscription function (empty constructor call) - // and no operator, but does have a source, the `subscribe` method will just - // subscribe the source - super(); - this.source = source; - - this.marker = marker; - } -} - -export const markName = - (name: string): MonoTypeOperatorFunction => - (observable$) => - new MarkedObservable(observable$, { - type: MarkerType.NAME, - sources: [findMarker(observable$)], - name, - }); - -export const markOfType = - (sources: ActionMarker[]): MonoTypeOperatorFunction => - (observable$) => - new MarkedObservable(observable$, { - type: MarkerType.OF_TYPE, - sources, - }); - -export const markCombineLatest = - (sources$: Observable[]): MonoTypeOperatorFunction => - (observable$) => - new MarkedObservable(observable$, { - type: MarkerType.COMBINE_LATEST, - sources: sources$.map(findMarker), - }); - -export const markWithLatestFrom = - ( - source$: Observable, - dependencies$: Observable[] - ): MonoTypeOperatorFunction => - (observable$) => - new MarkedObservable(observable$, { - type: MarkerType.WITH_LATEST_FROM, - sources: [findMarker(source$)], - dependencies: dependencies$.map(findMarker), - }); - -export const markMerge = - (sources$: Observable[]): MonoTypeOperatorFunction => - (observable$) => - new MarkedObservable(observable$, { - type: MarkerType.MERGE, - sources: sources$.map(findMarker), - }); - -export const markZip = - (sources$: Observable[]): MonoTypeOperatorFunction => - (observable$) => - new MarkedObservable(observable$, { - type: MarkerType.ZIP, - sources: sources$.map(findMarker), - }); - -export const markDebounceTime = - ( - source$: Observable, - time: number - ): MonoTypeOperatorFunction => - (observable$) => - new MarkedObservable(observable$, { - type: MarkerType.DEBOUNCE_TIME, - sources: [findMarker(source$)], - time, - }); - -export const findMarker = ( - observable$: ObservableInput -): Marker | null => { - if (observable$ instanceof MarkedObservable) { - return observable$.marker; - } else if ( - (observable$ as Observable).source instanceof Observable - ) { - return findMarker((observable$ as any).source); - } - return null; -}; diff --git a/src/internal/types.ts b/src/internal/types.ts index 04e210ab..904115e9 100644 --- a/src/internal/types.ts +++ b/src/internal/types.ts @@ -1,5 +1,4 @@ import { ActionWithPayload, ActionWithoutPayload } from '../types/Action'; -import { ActionMarker } from './markers'; export { VoidPayload } from '../types/Action'; @@ -14,7 +13,6 @@ export type UnknownAction = ActionWithoutPayload & { payload?: unknown }; export interface ActionCreatorCommon { readonly type: string; - readonly _marker: ActionMarker; } /** diff --git a/src/namespace.spec.ts b/src/namespace.spec.ts index 8b8a0f53..8389bd15 100644 --- a/src/namespace.spec.ts +++ b/src/namespace.spec.ts @@ -2,7 +2,6 @@ import test from 'ava'; import { namespaceActionCreator, namespaceActionDispatcher } from './namespace'; import { ActionDispatcher } from './types/helpers'; import { UnknownAction } from './internal/types'; -import { actionMarker } from './internal/markers'; import { _namespaceAction } from './namespace'; import { mockAction } from './internal/testing/utils'; @@ -45,7 +44,6 @@ test('namespaceActionCreator should create actions with namespace', (t) => { const actionCreator = (payload: number) => mockAction(type, 'old namespace', payload); actionCreator.type = type; - actionCreator._marker = actionMarker(type); const namespacedActionCreator = namespaceActionCreator( namespace, diff --git a/src/operators/decorated.spec.ts b/src/operators/decorated.spec.ts deleted file mode 100644 index f5739c23..00000000 --- a/src/operators/decorated.spec.ts +++ /dev/null @@ -1,139 +0,0 @@ -import test from 'ava'; -import { Observable } from 'rxjs'; -import { - MarkerType, - NameMarker, - findMarker, - markName, -} from '../internal/markers'; -import { - combineLatestWith, - debounceTime, - mergeWith, - startWith, - withLatestFrom, -} from './decorated'; -import { marbles } from 'rxjs-marbles/ava'; - -const source$ = new Observable().pipe(markName('source')); -const dependency1$ = source$.pipe(markName('dependency1')); -const dependency2$ = source$.pipe(markName('dependency2')); - -const source: NameMarker = { - type: MarkerType.NAME, - name: 'source', - sources: [null], -}; -const dependency1: NameMarker = { - type: MarkerType.NAME, - name: 'dependency1', - sources: [source], -}; -const dependency2: NameMarker = { - type: MarkerType.NAME, - name: 'dependency2', - sources: [source], -}; - -const letters = { a: 'A', b: 'B', c: 'C' }; -const combined = { - B: ['A', 'B'] as [string, string], - C: ['C', 'B'] as [string, string], -}; - -test('mergeWith adds name and mergeWith marker', (t) => { - const merged$ = source$.pipe(mergeWith(dependency1$, dependency2$)); - - t.deepEqual(findMarker(merged$), { - type: MarkerType.MERGE, - sources: [source, dependency1, dependency2], - }); -}); - -test( - 'mergeWith emits for each emit from source', - marbles((m) => { - const alpha$ = m.hot(' a-c', letters); - const bravo$ = m.hot(' -b-', letters); - const merged$ = m.hot('abc', letters); - - m.expect(alpha$.pipe(mergeWith(bravo$))).toBeObservable(merged$); - }) -); - -test('withLatestFrom adds name and combine marker', (t) => { - const derived$ = source$.pipe(withLatestFrom(dependency1$, dependency2$)); - - t.deepEqual(findMarker(derived$), { - type: MarkerType.WITH_LATEST_FROM, - sources: [source], - dependencies: [dependency1, dependency2], - }); -}); - -test( - 'withLatestFrom emits on emit from source', - marbles((m) => { - const alpha$ = m.hot(' a-c', letters); - const bravo$ = m.hot(' -b-', letters); - const combined$ = m.hot('--C', combined); - - m.expect(alpha$.pipe(withLatestFrom(bravo$))).toBeObservable(combined$); - }) -); - -test('combineLatestWith adds name and mergeWith marker', (t) => { - const combined$ = source$.pipe(combineLatestWith(dependency1$, dependency2$)); - - t.deepEqual(findMarker(combined$), { - type: MarkerType.COMBINE_LATEST, - sources: [source, dependency1, dependency2], - }); -}); - -test( - 'combineLatestWith emits for each emit from source', - marbles((m) => { - const alpha$ = m.hot(' a-c', letters); - const bravo$ = m.hot(' -b-', letters); - const combined$ = m.hot('-BC', combined); - - m.expect(alpha$.pipe(combineLatestWith(bravo$))).toBeObservable(combined$); - }) -); - -test('startWith adds parent marker', (t) => { - const startWith$ = source$.pipe(startWith(null)); - - t.deepEqual(findMarker(startWith$), source); -}); - -test( - 'startWith emits', - marbles((m) => { - const alpha$ = m.hot(' --c', letters); - const startWith$ = m.hot('a-c', letters); - - m.expect(alpha$.pipe(startWith(letters.a))).toBeObservable(startWith$); - }) -); - -test( - 'debounceTime emits with delay', - marbles((m) => { - const alpha$ = m.hot(' a-c', letters); - const expected$ = m.hot('-a-c', letters); - - m.expect(alpha$.pipe(debounceTime(1))).toBeObservable(expected$); - }) -); - -test('debounceTime places marker with time', (t) => { - const piped$ = source$.pipe(debounceTime(15)); - - t.deepEqual(findMarker(piped$), { - type: MarkerType.DEBOUNCE_TIME, - sources: [source], - time: 15, - }); -}); diff --git a/src/operators/decorated.ts b/src/operators/decorated.ts deleted file mode 100644 index 72df1a91..00000000 --- a/src/operators/decorated.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { Observable, SchedulerLike } from 'rxjs'; -import * as operators from 'rxjs/operators'; -import { - MarkedObservable, - findMarker, - markCombineLatest, - markDebounceTime, - markMerge, - markWithLatestFrom, -} from '../internal/markers'; - -export const mergeWith = ((...sources: Observable[]) => - (observable$: Observable) => - observable$.pipe( - operators.mergeWith(...sources), - markMerge([observable$, ...sources]) - )) as typeof operators.mergeWith; - -export const withLatestFrom = ((...dependencies: Observable[]) => - (observable$: Observable) => - observable$.pipe( - operators.withLatestFrom(...dependencies), - markWithLatestFrom(observable$, dependencies) - )) as typeof operators.withLatestFrom; - -export const combineLatestWith = (( - source: Observable, - ...sources: Observable[] - ) => - (observable$: Observable) => - observable$.pipe( - operators.combineLatestWith(source, ...sources), - markCombineLatest([observable$, source, ...sources]) - )) as typeof operators.combineLatestWith; - -export const startWith = ((...args: any) => - (observable$: Observable) => { - const startWith$ = observable$.pipe(operators.startWith(...args)); - const marker = findMarker(observable$); - if (marker === null) return startWith$; - return new MarkedObservable(startWith$, marker); - // only one of the overloads is deprecated - // tslint:disable-next-line deprecation - }) as typeof operators.startWith; - -export const debounceTime: typeof operators.debounceTime = - (dueTime: number, scheduler?: SchedulerLike) => - (observable$: Observable) => - observable$.pipe( - operators.debounceTime(dueTime, scheduler), - markDebounceTime(observable$, dueTime) - ); diff --git a/src/operators/index.ts b/src/operators/index.ts index a14f69bb..59cd42a7 100644 --- a/src/operators/index.ts +++ b/src/operators/index.ts @@ -6,12 +6,5 @@ export { carry, apply, } from './operators'; -export { - withLatestFrom, - combineLatestWith, - mergeWith, - startWith, - debounceTime, -} from './decorated'; export { mergeOperators } from './mergeOperators'; export { reduceState } from './reduceState'; diff --git a/src/operators/operators.spec.ts b/src/operators/operators.spec.ts index bf610380..6dd86825 100644 --- a/src/operators/operators.spec.ts +++ b/src/operators/operators.spec.ts @@ -13,9 +13,7 @@ import { } from './operators'; import { mockAction } from '../internal/testing/utils'; import { map } from 'rxjs/operators'; -import { Observable, pipe } from 'rxjs'; -import { UnknownAction } from '../internal/types'; -import { MarkerType, OfTypeMarker, findMarker } from '../internal/markers'; +import { pipe } from 'rxjs'; import { incrementMocks } from '../internal/testing/mock'; const { @@ -82,29 +80,6 @@ test( }) ); -test('ofType should add a stream marker', (t) => { - const piped$ = new Observable().pipe(ofType(voidAction)); - - t.deepEqual(findMarker(piped$), { - type: MarkerType.OF_TYPE, - sources: [ - { - type: MarkerType.ACTION, - name: voidAction.type, - }, - ], - }); -}); - -test('ofType markers should have reference equality of action marker', (t) => { - const one$ = new Observable().pipe(ofType(voidAction)); - const two$ = new Observable().pipe(ofType(voidAction)); - const one = findMarker(one$) as OfTypeMarker; - const two = findMarker(two$) as OfTypeMarker; - - t.assert(one.sources[0] === two.sources[0]); -}); - test( 'ofType should filter multiple actions that are mix of void and not void', marbles((m) => { diff --git a/src/operators/operators.ts b/src/operators/operators.ts index bf50edcd..138979fe 100644 --- a/src/operators/operators.ts +++ b/src/operators/operators.ts @@ -6,7 +6,6 @@ import { UnknownActionCreator, UnknownActionCreatorWithPayload, } from '../internal/types'; -import { markOfType } from '../internal/markers'; interface OfType { /** @@ -74,10 +73,7 @@ export const ofType: OfType = (( ): OperatorFunction => { const types = new Set(targetTypes.map(({ type }) => type)); - return pipe( - filter((action: UnknownAction) => types.has(action.type)), - markOfType(targetTypes.map(({ _marker }) => _marker)) - ); + return pipe(filter((action: UnknownAction) => types.has(action.type))); }) as any; // Implementation is untyped /** diff --git a/src/operators/reduceState.ts b/src/operators/reduceState.ts index 5cd1373e..eb5efbe5 100644 --- a/src/operators/reduceState.ts +++ b/src/operators/reduceState.ts @@ -1,4 +1,3 @@ -import { markName } from '../internal/markers'; import { UnknownAction } from '../internal/types'; import { defaultErrorSubject } from '../internal/defaultErrorSubject'; import { tag } from 'rxjs-spy/operators'; @@ -46,6 +45,5 @@ export const reduceState = ( refCount: true, bufferSize: 1, }), - markName(name), tag(name) ); diff --git a/src/persistentReducedStream.ts b/src/persistentReducedStream.ts index 5e986f5d..83a36d82 100644 --- a/src/persistentReducedStream.ts +++ b/src/persistentReducedStream.ts @@ -5,7 +5,6 @@ import { stateStreamRegistry } from './stateStreamRegistry'; import { action$ as defaultAction$ } from './action$'; import { ActionStream } from './types/helpers'; import { withNamespace } from './operators'; -import { markName } from './internal'; import { tag } from 'rxjs-spy/operators'; type PersistentReducedStreamOptions = { @@ -41,7 +40,7 @@ type PersistentReducedStreamOptions = { * myState$.startReducing(action$) // To start reducing * ``` * - * @param name The name of the stream, used for placing a marker and spy tag + * @param name The name of the stream, used for placing a spy tag * @param initialState The initial state of the stream * @param reducers The reducers that build up the stream state */ @@ -60,7 +59,6 @@ export const persistentReducedStream = ( errorSubject: errorSubject, namespace: namespace, }), - markName(name), tag(name) ); From 49b3840e5fc4efe35aa9001e761c65baf8266470 Mon Sep 17 00:00:00 2001 From: Tobias Laundal Date: Wed, 17 Aug 2022 14:18:28 +0200 Subject: [PATCH 2/2] feat: remove performance measurement --- .../performance/performanceMeasurements.ts | 43 ------------------- src/operators/reduceState.ts | 1 - src/reducer.ts | 22 +--------- 3 files changed, 2 insertions(+), 64 deletions(-) delete mode 100644 src/internal/performance/performanceMeasurements.ts diff --git a/src/internal/performance/performanceMeasurements.ts b/src/internal/performance/performanceMeasurements.ts deleted file mode 100644 index 146416be..00000000 --- a/src/internal/performance/performanceMeasurements.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { defaultErrorSubject } from '../defaultErrorSubject'; -import { Subject } from 'rxjs'; - -const PERFORMANCE_MARK_PREFIX = 'rxbeach'; - -const isWindowPerformanceDefined = () => - typeof window !== 'undefined' && window.performance; - -const getPerformanceMarker = (name: string) => { - return `${PERFORMANCE_MARK_PREFIX} - ${name}`; -}; - -const getStartMarker = (marker: string) => `${marker} - start`; -const getEndMarker = (marker: string) => `${marker} - end`; - -export const startPerformanceMeasurement = ( - name: string, - errorSubject: Subject = defaultErrorSubject -) => { - if (!isWindowPerformanceDefined()) return; - try { - const marker = getStartMarker(getPerformanceMarker(name)); - window.performance.mark(marker); - } catch (e) { - errorSubject.next(e); - } -}; - -export const endPerformanceMeasurement = ( - name: string, - errorSubject: Subject = defaultErrorSubject -) => { - if (!isWindowPerformanceDefined()) return; - const marker = getPerformanceMarker(name); - const startMarker = getStartMarker(marker); - const endMarker = getEndMarker(marker); - try { - window.performance.mark(endMarker); - window.performance.measure(marker, startMarker, endMarker); - } catch (e) { - errorSubject.next(e); - } -}; diff --git a/src/operators/reduceState.ts b/src/operators/reduceState.ts index eb5efbe5..bd789425 100644 --- a/src/operators/reduceState.ts +++ b/src/operators/reduceState.ts @@ -38,7 +38,6 @@ export const reduceState = ( pipe( combineReducers(defaultState, reducers, { errorSubject, - performanceMarker: name, }), startWith(defaultState), shareReplay({ diff --git a/src/reducer.ts b/src/reducer.ts index 871265ec..36e0924b 100644 --- a/src/reducer.ts +++ b/src/reducer.ts @@ -7,7 +7,7 @@ import { from, pipe, } from 'rxjs'; -import { filter, map, mergeWith, scan, tap } from 'rxjs/operators'; +import { filter, map, mergeWith, scan } from 'rxjs/operators'; import { UnknownAction, UnknownActionCreator, @@ -16,10 +16,6 @@ import { } from './internal/types'; import { defaultErrorSubject } from './internal/defaultErrorSubject'; import { ofType } from './operators/operators'; -import { - endPerformanceMeasurement, - startPerformanceMeasurement, -} from './internal/performance/performanceMeasurements'; import { isObservableInput } from './isObservableInput'; const wrapInArray = (val: T | T[]): T[] => @@ -193,7 +189,6 @@ const ACTION_ORIGIN = Symbol('Action origin'); type CombineReducersConfig = { errorSubject?: Subject; - performanceMarker?: string; namespace?: string; }; @@ -218,9 +213,6 @@ type CombineReducersConfig = { * `defaultErrorSubject`, which will rethrow the errors globally, as uncaught * exceptions. The stream will not complete or emit any value upon an error. * - * If a performanceMarker is passed, combineReducers will add performance marks - * using the window.performance API - * * @param seed The initial input to the first reducer call * @param reducers The reducer entries that should be combined * @param namespace Namespace to pass on to the reducers. Note that this will @@ -230,11 +222,7 @@ type CombineReducersConfig = { export const combineReducers = ( seed: State, reducers: RegisteredReducer[], - { - errorSubject = defaultErrorSubject, - performanceMarker, - namespace, - }: CombineReducersConfig = {} + { errorSubject = defaultErrorSubject, namespace }: CombineReducersConfig = {} ): OperatorFunction => { const actionReducers = reducers.filter(isActionReducer); const streamReducers = reducers.filter(isStreamReducer); @@ -261,9 +249,6 @@ export const combineReducers = ( ofType(...actionReducers.flatMap((reducerFn) => reducerFn.trigger.actions)), map((action): Packet => ({ origin: ACTION_ORIGIN, value: action })), mergeWith(...source$s), - tap(() => { - if (performanceMarker) startPerformanceMeasurement(performanceMarker); - }), scan( ({ state }, packet) => { try { @@ -290,9 +275,6 @@ export const combineReducers = ( }, { state: seed, caughtError: false } ), - tap(() => { - if (performanceMarker) endPerformanceMeasurement(performanceMarker); - }), filter(({ caughtError }) => caughtError === false), map(({ state }) => state) );