Xstate machine - Load feature flags

192 Views Asked by At

What we need to do: We need to feature flag a few things in our current state machine

My ideal solution: Always load, no matter what state is, all feature flags and assign them to the state machine context

Attempts: Tried using async actions and invoke services, however, I cannot find a way to always run either of them

This basically my state machine and how I envisioned loading feature flag. However, the invoke.src function just gets called for the first time when I'm first loading the state machine.

Every time that I hydrate the state machine and the state machine is in one of the state, for example create, the invoke.src function does not get called therefore no FF is loaded into the context

const stateMachine = createStateMachine({
    id: 'state-machine',
    invoke: {
        src: async () => {
           return await featureFlagService.load();
        },
       onDone: {
         actions: assign(_context, event) => ({ featureFlagEvaluations: event.data }),
       }
    },
    states: {
        'create': { ... },
        'retrieve': { ... },
    }
});

Does anyone have any idea of how to implement such use case?

1

There are 1 best solutions below

0
On

You should use the actor model approach. Each time when you need to refresh/fetch the FF you should spawn FF-machine and on done call parentSend() message which will update the context to your main SM(state-machine)

const stateMachine = createStateMachine({
    id: 'state-machine',
    invoke: {
        src: async () => {
           return await featureFlagService.load();
        },
       onDone: [{
         actions:  assign({
         ffActorRef: () => spawn(featureFlagMachine, 'ffActor'),
      }),
    }],
    states: {
        'create': { ... },
        'retrieve': { ... },
    },
    on:{
        REFRESH_FEATURE_FLAG : [{
         actions: assign(_context, event) => ({ featureFlagEvaluations: event.data }),
        }]
    }
});

const featureFlagMachine = createStateMachine({
    id: 'ff-machine',
    initial: 'retrieve',
    invoke: {
        src: async () => {
           return await featureFlagService.load();
        },
       onDone: [{
         actions: ['notifyRefresh']
    }],
    states: {
        'create': { ... },
        'retrieve': { ... },
    },
},
{
       actions: {
        notifyRefresh: sendParent((ctx, event) => {
        return {
          type: 'REFRESH_FEATURE_FLAG',
          data: { featureFlagEvaluations: event.data },
        };
      }),
    },
  }

}

);