movex icon indicating copy to clipboard operation
movex copied to clipboard

[Discussion] Add an api for "jobs" or "actions" to run on the server ONLY

Open GabrielCTroia opened this issue 9 months ago • 1 comments

What

Sometimes it's important for some actions/jobs to run on the server (only).

Such an example is a state that need to be updated every N seconds, or every certain action such as a report or "game timeout". At the moment such a thing can be "maintained" by a client, which acts as the host or the master, but of course this can be problematic for a bunch of reasons:

  1. clients CANNOT be trusted 100% (as they can be hacked)
  2. it requires the client to be active, but what if the client closes the connection for whatever reason?

Proposition

Add a jobs field to the Movex Definition file such as:

// movex.definition.ts

import roomReducer from './game/movex/reducer';

export default {
  resources: {
    game: gameReducer,
  },

  // These only happen on the server
  jobs: {
    on: {
      resources: {
        room: {
          actions: {
            ''
          }
        }
      },
      time: {},
    },
  }
};

The jobs object defines what the "event triggers" are and what happens when they do get triggered (i.e. the state update).

They can be:

1. Resource actions

Before or after a certain action gets triggered, like:

const CountMovesJob = (currentState: State) => {
  return {
    ...currentState,
   movesCount: currentState.movesCount + 1,
  }
}

// every time a "game:move" Action dispatches, call the "CountMovesJob" job

It could be defined something like this:

// movex.definition.ts

jobs: {
    on: {
      resources: {
        room: {
          actions: {
            after: {
              move: CountMovesJob,
            }
          }
        }
      },
    },
  }

2. Time based

How does the state get updated?

The master-state already takes priority over the client state, meaning the client reducers are only called for eager rendering, therefore, the change here is the master will run the jobs according to the event triggers (i.e. before/after an action gets dispatched or time based)

GabrielCTroia avatar May 02 '24 23:05 GabrielCTroia

A new idea to solve this, at least for some use cases, is to transform the state at read time. Meaning that the state won't be updated unless needed – no action needs to run in the background, but when an API call (or a client call) asks for the current state, it runs through a $transformState function.

The $transformState receives the currentState as well as a MovexRemoteContext object that will provide information such as date/time or other Movex Related data in order to determine the next version of the state.

This function will only run on the server! And based on how Movex works, it will auto correct the eagerly computed client states when a $transformer returns a different state!

GabrielCTroia avatar Jul 16 '24 13:07 GabrielCTroia

This, or at least a good part of this was solved when we introduced $transformState and MasterActions #221

GabrielCTroia avatar Oct 12 '24 18:10 GabrielCTroia