fix(marketplace): close client review findings
This commit is contained in:
@@ -93,12 +93,13 @@ export function createPluginMarketplaceStore(
|
||||
let catalogGeneration = 0;
|
||||
let libraryIntent = 0;
|
||||
let latestLibraryReadIntent = 0;
|
||||
const latestPluginMutationIntent = new Map<string, number>();
|
||||
const latestLibraryMutationIntent = new Map<string, number>();
|
||||
const latestDeviceMutationIntent = new Map<string, number>();
|
||||
|
||||
return createStore<PluginMarketplaceState>((set, get) => {
|
||||
const beginMutation = (pluginId: string): number => {
|
||||
const beginMutation = (pluginId: string, domain: 'library' | 'device'): number => {
|
||||
const intent = ++libraryIntent;
|
||||
latestPluginMutationIntent.set(pluginId, intent);
|
||||
(domain === 'library' ? latestLibraryMutationIntent : latestDeviceMutationIntent).set(pluginId, intent);
|
||||
return intent;
|
||||
};
|
||||
|
||||
@@ -107,12 +108,18 @@ export function createPluginMarketplaceStore(
|
||||
intent: number,
|
||||
generation: number,
|
||||
accountKey: string,
|
||||
domain: 'library' | 'device',
|
||||
): boolean => generation === scopeGeneration
|
||||
&& get().accountKey === accountKey
|
||||
&& latestPluginMutationIntent.get(pluginId) === intent
|
||||
// A later explicit read is the newest account projection for every
|
||||
// plugin, so an older mutation must not replace it.
|
||||
&& latestLibraryReadIntent <= intent;
|
||||
&& (domain === 'library' ? latestLibraryMutationIntent : latestDeviceMutationIntent).get(pluginId) === intent
|
||||
// A later explicit read is the newest Library projection, so an older
|
||||
// Library mutation must not replace it. Device state is independent.
|
||||
&& (domain === 'device' || latestLibraryReadIntent <= intent);
|
||||
|
||||
const latestPluginMutationIntent = (pluginId: string): number => Math.max(
|
||||
latestLibraryMutationIntent.get(pluginId) ?? 0,
|
||||
latestDeviceMutationIntent.get(pluginId) ?? 0,
|
||||
);
|
||||
|
||||
const mergeLibraryForPlugin = (
|
||||
current: MarketplaceLibrarySnapshot | null,
|
||||
@@ -125,8 +132,8 @@ export function createPluginMarketplaceStore(
|
||||
if (incomingItem) byPlugin.set(pluginId, incomingItem);
|
||||
else byPlugin.delete(pluginId);
|
||||
const items = [...byPlugin.values()].sort((left, right) => {
|
||||
const leftIntent = latestPluginMutationIntent.get(left.pluginId) ?? 0;
|
||||
const rightIntent = latestPluginMutationIntent.get(right.pluginId) ?? 0;
|
||||
const leftIntent = latestPluginMutationIntent(left.pluginId);
|
||||
const rightIntent = latestPluginMutationIntent(right.pluginId);
|
||||
return rightIntent - leftIntent;
|
||||
});
|
||||
return {
|
||||
@@ -170,10 +177,10 @@ export function createPluginMarketplaceStore(
|
||||
const generation = scopeGeneration;
|
||||
const accountKey = get().accountKey;
|
||||
if (!accountKey) throw new Error('请先登录后管理我的插件');
|
||||
const intent = beginMutation(pluginId);
|
||||
const intent = beginMutation(pluginId, 'library');
|
||||
try {
|
||||
const projection = await action(pluginId);
|
||||
if (!canCommitMutation(pluginId, intent, generation, accountKey)) return;
|
||||
if (!canCommitMutation(pluginId, intent, generation, accountKey, 'library')) return;
|
||||
const merged = mergeLibraryProjection(pluginId, projection);
|
||||
set({
|
||||
library: merged.library,
|
||||
@@ -182,7 +189,7 @@ export function createPluginMarketplaceStore(
|
||||
libraryError: null,
|
||||
});
|
||||
} catch (error) {
|
||||
if (canCommitMutation(pluginId, intent, generation, accountKey)) {
|
||||
if (canCommitMutation(pluginId, intent, generation, accountKey, 'library')) {
|
||||
set({ libraryError: message(error) });
|
||||
}
|
||||
throw error;
|
||||
@@ -197,10 +204,10 @@ export function createPluginMarketplaceStore(
|
||||
const generation = scopeGeneration;
|
||||
const accountKey = get().accountKey;
|
||||
if (!accountKey) throw new Error('请先登录后管理设备插件');
|
||||
const intent = beginMutation(pluginId);
|
||||
const intent = beginMutation(pluginId, 'device');
|
||||
try {
|
||||
const result = await action(pluginId);
|
||||
if (!canCommitMutation(pluginId, intent, generation, accountKey)) return;
|
||||
if (!canCommitMutation(pluginId, intent, generation, accountKey, 'device')) return;
|
||||
set((state) => {
|
||||
const installations = { ...state.installations };
|
||||
if (result.status === 'removed') delete installations[pluginId];
|
||||
@@ -208,7 +215,7 @@ export function createPluginMarketplaceStore(
|
||||
return { installations, libraryError: null };
|
||||
});
|
||||
} catch (error) {
|
||||
if (canCommitMutation(pluginId, intent, generation, accountKey)) {
|
||||
if (canCommitMutation(pluginId, intent, generation, accountKey, 'device')) {
|
||||
const reason = message(error);
|
||||
set((state) => ({
|
||||
installations: {
|
||||
@@ -250,7 +257,8 @@ export function createPluginMarketplaceStore(
|
||||
scopeGeneration += 1;
|
||||
libraryIntent += 1;
|
||||
latestLibraryReadIntent = libraryIntent;
|
||||
latestPluginMutationIntent.clear();
|
||||
latestLibraryMutationIntent.clear();
|
||||
latestDeviceMutationIntent.clear();
|
||||
set({
|
||||
accountKey,
|
||||
library: null,
|
||||
|
||||
Reference in New Issue
Block a user