Logux stores metadata for every action in separated object:
log = [
[action1, meta1],
[action2, meta2],
…
]Meta contains Logux-related data. It should not contain anything related to application state.
Meta has unique action’s ID, creating time, processing status and many other things. Meta is open structure, applications can set custom keys to meta object.
{
added: 5,
id: "1564508138460 380:R7BNGAP5:px3-J3oc 0",
reasons: ['amplifr/lastPrices'],
subprotocol: 10,
time: 1564508138460
}Setting Meta
Most of methods to add action accept meta as second arguments:
store.dispatch.sync(action, meta)
store.commit.sync(action, meta)
client.log.add(action, meta)
server.log.add(action, meta)
ctx.sendBack(action, meta)The only methods without meta argument:
store.dispatch(action). Use store.dispatch.local(action, meta) to set meta for local-tab actions.
store.commit(action). Use store.commit.local(action, meta) to set meta for local-tab actions.
Changing Meta
In Logux architecture, you can change application state only by adding new action to the log. This is why you can’t change action or action’s order.
Since meta doesn’t contain anything related to application state, you can change meta if it will not affect action’s order.
store.log.changeMeta(actionId, {
reasons: []
})
store.log.changeMeta(actionId, {
reasons: []
})
client.log.changeMeta(actionId, {
reasons: []
})
You can not change meta’s keys related to action’s order: id, time, added.
On the server you can set channels, users, clients and nodes keys (and singular versions) for new action from the client by resend callback. If you will return a string or an array of strings, server will set it as channels.
server.type('users/rename', {
…
resend (ctx, action, meta) {
return `users/${ action.userId }`
},
…
})
class RenameUserAction(ActionCommand):
action_type = 'user/rename'
def resend(self, action: Action, meta: Optional[Meta]) -> List[str]:
return [f"users/{action['payload']['userId']}"]
Under construction. Until resend will be implemented in the gem.
Meta Synchronization
Logux synchronizes only 3 meta’s keys:
idtime, but it will be changed to fix time difference between client and serversubprotocol
All other meta keys are local and both server and client do not send them.
ID and Time
Each action has unique ID. This ID is unique on all machines.
"1564508138460 380:R7BNGAP5:px3-J3oc 0"To generate ID unique across all nodes in Logux cluster, Logux combines 3 values:
1564508138460: local timestamp on the node, which generate the action.380:R7BNGAP5:px3-J3oc: unique ID of node, which generate the action.0is a counter for the case, when node will generate several actions during the same timestamp.
log.generateId() //=> "1564508138460 380:R7BNGAP5:px3-J3oc 0"
log.generateId() //=> "1564508138460 380:R7BNGAP5:px3-J3oc 1"
log.generateId() //=> "1564508138461 380:R7BNGAP5:px3-J3oc 0"In real world, every node will have own time. For instance, user could set wrong time on own phone. This is why you should not use meta.id as a time. Logux has special meta.time, which will use time of current node. During the connection client and server will calculate time difference between them and change meta.time during synchronization. As result, meta.time could be different on different nodes.
const time = new Date(meta.time) //=> Date 2019-07-30T17:35:38.460Zmeta.time is a timestamp. Few actions can have the same meta.time if these actions was generated very fast in the same millisecond. Logux has isFirstOlder helper, which uses both meta.time and meta.id to always be sure what action was generated later.
import { isFirstOlder } from '@logux/core'
if (isFirstOlder(meta1, meta2)) {
lastName = action1.name
} else {
lastName = action2.name
}Common Meta Keys
These meta’s keys are available on client and server:
idstring: unique action’s ID.timetimestamp: when action was created. It uses local node’s time.addednumber: action’s serial number. Logux uses this number to track what actions were already synchronized.reasonsarray of strings: reasons for action to not be cleaned from log. We will cover it in next chapter.subprotocolnumber: subprotocol of application, which generates this action.
Client Meta Keys
syncboolean: optional key to mark that this action should be synchronized with other browser tabs and server.tabstring: optional key to mark that action should be visible only for browser tab with the sameclient.tabId.noAutoReasonboolean: optional key to disable settingtimeTravelreason.
Server Meta Keys
status"waiting"|"processed"|"error": action processing status.serverstring: node ID of the server received the action.channelsarray andchannelstring: all clients subscribed to listed channels will receive the action.usersarray anduserstring: all clients with listed user IDs will receive the action.clientsarray andclientstring: all clients with listed client IDs will receive the action.nodesarray andnodestring: all clients with listed node IDs will receive the action.