fix test failures etc

This commit is contained in:
Gareth George
2026-05-02 22:27:28 -07:00
parent 8b8d85528b
commit b758ec7443
3 changed files with 212 additions and 131 deletions
+29 -22
View File
@@ -280,28 +280,27 @@ func (c *syncSessionHandlerClient) OnConnectionEstablished(ctx context.Context,
c.mgr.peerStateManager.SetPeerState(peer.Keyid, peerState)
// Clear the pairing secret from the known host entry now that pairing has succeeded.
if c.syncConfigSnapshot.config.GetMultihost() != nil {
for _, knownHost := range c.syncConfigSnapshot.config.GetMultihost().GetKnownHosts() {
if knownHost.GetKeyid() == peer.GetKeyid() && knownHost.GetInitialPairingSecret() != "" {
cfg, err := c.mgr.configMgr.Get()
if err != nil {
c.l.Sugar().Warnf("failed to get config to clear pairing secret: %v", err)
break
}
cfg = proto.Clone(cfg).(*v1.Config)
for _, kh := range cfg.GetMultihost().GetKnownHosts() {
if kh.GetKeyid() == peer.GetKeyid() {
kh.InitialPairingSecret = ""
break
}
}
cfg.Modno++
if err := c.mgr.configMgr.Update(cfg); err != nil {
c.l.Sugar().Warnf("failed to clear pairing secret after successful pairing: %v", err)
} else {
c.l.Sugar().Infof("cleared pairing secret for peer %q after successful connection", peer.InstanceId)
}
break
knownHosts := c.syncConfigSnapshot.config.GetMultihost().GetKnownHosts()
khIdx := slices.IndexFunc(knownHosts, func(kh *v1.Multihost_Peer) bool {
return kh.GetKeyid() == peer.GetKeyid()
})
if khIdx >= 0 && knownHosts[khIdx].GetInitialPairingSecret() != "" {
cfg, err := c.mgr.configMgr.Get()
if err != nil {
c.l.Sugar().Warnf("failed to get config to clear pairing secret: %v", err)
} else {
cfg = proto.Clone(cfg).(*v1.Config)
liveIdx := slices.IndexFunc(cfg.GetMultihost().GetKnownHosts(), func(kh *v1.Multihost_Peer) bool {
return kh.GetKeyid() == peer.GetKeyid()
})
if liveIdx >= 0 {
cfg.GetMultihost().GetKnownHosts()[liveIdx].InitialPairingSecret = ""
}
cfg.Modno++
if err := c.mgr.configMgr.Update(cfg); err != nil {
c.l.Sugar().Warnf("failed to clear pairing secret after successful pairing: %v", err)
} else {
c.l.Sugar().Infof("cleared pairing secret for peer %q after successful connection", peer.InstanceId)
}
}
}
@@ -517,6 +516,14 @@ func (c *syncSessionHandlerClient) HandleSetConfig(ctx context.Context, stream *
if idx >= 0 {
latestConfig.Repos[idx] = repo
} else {
// Check for conflicts with existing local repos by ID or URI
conflictIdx := slices.IndexFunc(latestConfig.Repos, func(r *v1.Repo) bool {
return r.Id == repo.Id || r.Uri == repo.Uri
})
if conflictIdx >= 0 {
c.l.Sugar().Warnf("received shared repo %q (guid %s) conflicts with existing local repo %q (guid %s), skipping", repo.Id, repo.Guid, latestConfig.Repos[conflictIdx].Id, latestConfig.Repos[conflictIdx].Guid)
continue
}
latestConfig.Repos = append(latestConfig.Repos, repo)
}
}
+3 -2
View File
@@ -520,9 +520,10 @@ func (h *syncSessionHandlerServer) HandleOperationManifest(ctx context.Context,
}
}
// Find ops we need (new or changed modno)
// Find ops we need (new or changed modno), preserving manifest order
var needIDs []int64
for id, modno := range remoteSet {
for i, id := range item.GetOpIds() {
modno := item.GetModnos()[i]
local, exists := localState[id]
if !exists || local.modno != modno {
needIDs = append(needIDs, id)
+180 -107
View File
@@ -13,6 +13,7 @@ import {
FiEdit2,
FiMenu,
FiHome,
FiChevronRight,
} from "react-icons/fi";
import {
@@ -256,6 +257,175 @@ const PlanViewContainer = () => {
);
};
const PeerNavItem = ({
icon,
typeLabel,
name,
active,
onClick,
onEdit,
}: {
icon: React.ReactNode;
typeLabel: string;
name: string;
active: boolean;
onClick: () => void;
onEdit?: (e: React.MouseEvent) => void;
}) => (
<Flex
align="center"
pl={14}
pr={2}
py={1}
bg={active ? "bg.emphasized" : undefined}
_hover={{ bg: "bg.muted" }}
cursor="pointer"
className="group"
onClick={onClick}
>
<Box flexShrink={0} mr={2}>
{icon}
</Box>
<Text color="fg.muted" fontSize="xs" flexShrink={0} mr={1}>
{typeLabel}
</Text>
<Text fontSize="sm" flex="1" wordBreak="break-word">
{name}
</Text>
{onEdit && (
<Box
opacity={0}
_groupHover={{ opacity: 1 }}
transition="opacity 0.2s"
>
<IconButton
size="xs"
variant="ghost"
onClick={(e: React.MouseEvent) => {
e.stopPropagation();
onEdit(e);
}}
>
<FiEdit2 />
</IconButton>
</Box>
)}
</Flex>
);
const PeerInstanceSection = ({
peerState,
sel,
remoteConfig,
isActive,
handleNav,
handleRemoteRepoEdit,
handleRemotePlanEdit,
}: {
peerState: PeerState;
sel: OpSelector;
remoteConfig: PeerState["remoteConfig"];
isActive: (path: string) => boolean;
handleNav: (path: string) => void;
handleRemoteRepoEdit: (repo: Repo) => void;
handleRemotePlanEdit: (plan: Plan) => void;
}) => {
const [expanded, setExpanded] = useState(false);
return (
<Box mb={2}>
<Flex
align="center"
pl={9}
pr={2}
py={1}
cursor="pointer"
_hover={{ bg: "bg.muted" }}
onClick={() => setExpanded((prev) => !prev)}
>
<Box
transform={expanded ? "rotate(90deg)" : undefined}
transition="transform 0.2s"
display="inline-flex"
alignItems="center"
mr={2}
flexShrink={0}
>
<FiChevronRight size={14} />
</Box>
<Box flexShrink={0} mr={2}>
<IconForResource selector={sel} />
</Box>
<Text fontWeight="bold" fontSize="sm">
{peerState.peerInstanceId}
</Text>
</Flex>
{expanded && (
<>
{peerState.knownRepos.map((repo: RepoMetadata) => {
const repoPath = `/peer/${peerState.peerInstanceId}/repo/${repo.id}`;
const editableRepo = remoteConfig?.repos?.find(
(r: Repo) => r.guid === repo.guid,
);
return (
<PeerNavItem
key={repo.guid}
icon={
<IconForResource
selector={create(OpSelectorSchema, {
originalInstanceKeyid: peerState.peerKeyid,
repoGuid: repo.guid,
})}
/>
}
typeLabel="repo"
name={repo.id}
active={isActive(repoPath)}
onClick={() => handleNav(repoPath)}
onEdit={
editableRepo
? () => handleRemoteRepoEdit(editableRepo)
: undefined
}
/>
);
})}
{peerState.knownPlans.map((planMeta: PlanMetadata) => {
const planPath = `/peer/${peerState.peerInstanceId}/plan/${planMeta.id}`;
const editablePlan = remoteConfig?.plans?.find(
(p: Plan) => p.id === planMeta.id,
);
return (
<PeerNavItem
key={planMeta.id}
icon={
<IconForResource
selector={create(OpSelectorSchema, {
originalInstanceKeyid: peerState.peerKeyid,
planId: planMeta.id,
})}
/>
}
typeLabel="plan"
name={planMeta.id}
active={isActive(planPath)}
onClick={() => handleNav(planPath)}
onEdit={
editablePlan
? () => handleRemotePlanEdit(editablePlan)
: undefined
}
/>
);
})}
</>
)}
</Box>
);
};
const SidebarPlanItem = React.memo(
({
plan,
@@ -640,113 +810,16 @@ const SidebarContent = ({ onClose }: { onClose?: () => void }) => {
};
return (
<Box key={peerState.peerKeyid} mb={2}>
<Flex align="center" pl={9} pr={2} py={1}>
<Box flexShrink={0} mr={2}>
<IconForResource selector={sel} />
</Box>
<Text fontWeight="bold" fontSize="sm">
{peerState.peerInstanceId}
</Text>
</Flex>
{/* Nested Repos for Peer — listed from knownRepos (READ_OPERATIONS), edit from remoteConfig (READ_CONFIG) */}
{peerState.knownRepos.map((repo: RepoMetadata) => {
const repoPath = `/peer/${peerState.peerInstanceId}/repo/${repo.id}`;
const active = isActive(repoPath);
const editableRepo = remoteConfig?.repos?.find((r: Repo) => r.guid === repo.guid);
return (
<Flex
key={repo.guid}
align="center"
pl={12}
pr={2}
py={1}
bg={active ? "bg.emphasized" : undefined}
_hover={{ bg: "bg.muted" }}
cursor="pointer"
className="group"
onClick={() => handleNav(repoPath)}
>
<Box flexShrink={0} mr={2}>
<IconForResource
selector={create(OpSelectorSchema, {
originalInstanceKeyid: peerState.peerKeyid,
repoGuid: repo.guid,
})}
/>
</Box>
<Text fontSize="sm" flex="1" wordBreak="break-word">
{repo.id}
</Text>
{editableRepo && (
<Box
opacity={0}
_groupHover={{ opacity: 1 }}
transition="opacity 0.2s"
>
<IconButton
size="xs"
variant="ghost"
onClick={(e: React.MouseEvent) => {
e.stopPropagation();
handleRemoteRepoEdit(editableRepo);
}}
>
<FiEdit2 />
</IconButton>
</Box>
)}
</Flex>
);
})}
{/* Nested Plans for Peer — listed from knownPlans, edit from remoteConfig */}
{peerState.knownPlans.map((planMeta: PlanMetadata) => {
const planPath = `/peer/${peerState.peerInstanceId}/plan/${planMeta.id}`;
const active = isActive(planPath);
const editablePlan = remoteConfig?.plans?.find((p: Plan) => p.id === planMeta.id);
return (
<Flex
key={planMeta.id}
align="center"
pl={12}
pr={2}
py={1}
bg={active ? "bg.emphasized" : undefined}
_hover={{ bg: "bg.muted" }}
cursor="pointer"
className="group"
onClick={() => handleNav(planPath)}
>
<Box flexShrink={0} mr={2}>
<FiCalendar />
</Box>
<Text fontSize="sm" flex="1" wordBreak="break-word">
{planMeta.id}
</Text>
{editablePlan && (
<Box
opacity={0}
_groupHover={{ opacity: 1 }}
transition="opacity 0.2s"
>
<IconButton
size="xs"
variant="ghost"
onClick={(e: React.MouseEvent) => {
e.stopPropagation();
handleRemotePlanEdit(editablePlan);
}}
>
<FiEdit2 />
</IconButton>
</Box>
)}
</Flex>
);
})}
</Box>
<PeerInstanceSection
key={peerState.peerKeyid}
peerState={peerState}
sel={sel}
remoteConfig={remoteConfig}
isActive={isActive}
handleNav={handleNav}
handleRemoteRepoEdit={handleRemoteRepoEdit}
handleRemotePlanEdit={handleRemotePlanEdit}
/>
);
})}
</AccordionItemContent>