feat(federation): record DM origin alternatives in spaceStore
Every DM arriving in a ready payload with a federatedId now gets its (origin, localChannelId) pair recorded in dmAlternatives, regardless of whether the dedup pass kept this copy in dmChannels. Enables client-side DM origin failover: when the primary origin drops, we can look up an alternate origin's local channel ID for the same federated DM. Prep for #10 (DM origin failover on disconnect).
This commit is contained in:
@@ -41,6 +41,8 @@ interface SpaceState {
|
||||
channelOriginMap: Map<string, string>; // channelId → instance origin ('' = home)
|
||||
voiceChannelIds: Set<string>; // channelIds that are voice channels (excluded from unread)
|
||||
categoryOriginMap: Map<string, string>; // categoryId → instance origin ('' = home)
|
||||
/** federatedId → (origin → localChannelId). Every DM from every origin's ready payload is recorded here regardless of dedup outcome, so failover can re-point to an alternate origin's local channel ID. */
|
||||
dmAlternatives: Map<string, Map<string, string>>;
|
||||
loadingSpaceId: string | null; // non-null while loadSpaceDetail is fetching
|
||||
_layoutUpdatedAt: number;
|
||||
setSpaces: (spaces: TaggedSpace[]) => void;
|
||||
@@ -132,6 +134,7 @@ export const useSpaceStore = create<SpaceState>((set, get) => ({
|
||||
channelOriginMap: new Map(),
|
||||
voiceChannelIds: new Set(),
|
||||
categoryOriginMap: new Map(),
|
||||
dmAlternatives: new Map(),
|
||||
loadingSpaceId: null,
|
||||
_layoutUpdatedAt: 0,
|
||||
|
||||
@@ -154,6 +157,7 @@ export const useSpaceStore = create<SpaceState>((set, get) => ({
|
||||
channelOriginMap: new Map(),
|
||||
voiceChannelIds: new Set(),
|
||||
categoryOriginMap: new Map(),
|
||||
dmAlternatives: new Map(),
|
||||
loadingSpaceId: null,
|
||||
_layoutUpdatedAt: 0,
|
||||
});
|
||||
@@ -584,6 +588,10 @@ export const useSpaceStore = create<SpaceState>((set, get) => ({
|
||||
const channelOriginMap = new Map(get().channelOriginMap);
|
||||
const voiceChannelIds = new Set(get().voiceChannelIds);
|
||||
const categoryOriginMap = new Map(get().categoryOriginMap);
|
||||
const dmAlternatives = new Map<string, Map<string, string>>();
|
||||
for (const [fid, byOrigin] of get().dmAlternatives) {
|
||||
dmAlternatives.set(fid, new Map(byOrigin));
|
||||
}
|
||||
|
||||
// If home, clear home-origin entries first to avoid stale data
|
||||
if (isHome) {
|
||||
@@ -688,6 +696,18 @@ export const useSpaceStore = create<SpaceState>((set, get) => ({
|
||||
}
|
||||
}
|
||||
|
||||
// Record every DM's (origin → localChannelId) for failover lookup,
|
||||
// regardless of whether the dedup pass kept this copy in dmChannels.
|
||||
for (const dm of incomingDms) {
|
||||
if (!dm.federatedId) continue;
|
||||
let byOrigin = dmAlternatives.get(dm.federatedId);
|
||||
if (!byOrigin) {
|
||||
byOrigin = new Map();
|
||||
dmAlternatives.set(dm.federatedId, byOrigin);
|
||||
}
|
||||
byOrigin.set(origin, dm.id);
|
||||
}
|
||||
|
||||
// Merge: remove DMs belonging to this origin from existing state, then append incoming
|
||||
const existingDmsFromOtherOrigins = get().dmChannels.filter(dm => {
|
||||
const dmOrigin = get().channelOriginMap.get(dm.id);
|
||||
@@ -711,6 +731,7 @@ export const useSpaceStore = create<SpaceState>((set, get) => ({
|
||||
channelOriginMap,
|
||||
voiceChannelIds,
|
||||
categoryOriginMap,
|
||||
dmAlternatives,
|
||||
};
|
||||
|
||||
// LWW layout merge: accept incoming layout only if its timestamp is >= ours
|
||||
|
||||
Reference in New Issue
Block a user