Update Harbor client and gateway functionality
This commit is contained in:
@@ -7,7 +7,10 @@ import {
|
||||
type StoredState,
|
||||
} from '../../../shared/contracts/state.js';
|
||||
import { HarborError } from '../../../shared/errors.js';
|
||||
import { normalizeRouteRules } from '../../../shared/routingRules.js';
|
||||
import {
|
||||
normalizeRouteRules,
|
||||
ROUTE_RULES_CONTRACT_VERSION,
|
||||
} from '../../../shared/routingRules.js';
|
||||
import type { RuntimeCommandResult } from '../connection/index.js';
|
||||
import { finishRollback } from '../../services/rollback.js';
|
||||
|
||||
@@ -29,6 +32,7 @@ interface RouteRulesDependencies {
|
||||
applyCommand(): Promise<RuntimeCommandResult>;
|
||||
restoreRunning(): Promise<unknown>;
|
||||
};
|
||||
route?: { isGatewayDirect(): boolean };
|
||||
serialize<T>(operation: () => Promise<T>): Promise<T>;
|
||||
runOperation<T>(operation: () => Promise<T>): Promise<T>;
|
||||
}
|
||||
@@ -36,6 +40,7 @@ interface RouteRulesDependencies {
|
||||
export function createRouteRulesService(dependencies: RouteRulesDependencies) {
|
||||
const applyRules = async (previousState: StoredState, routeRules: RouteRule[]) => {
|
||||
const wasRunning = await dependencies.runtime.isRunning();
|
||||
const bypassed = dependencies.route?.isGatewayDirect() === true;
|
||||
const targetProfile = wasRunning
|
||||
? appliedProfile(previousState)
|
||||
: desiredProfile(previousState);
|
||||
@@ -45,13 +50,14 @@ export function createRouteRulesService(dependencies: RouteRulesDependencies) {
|
||||
const subscriptionConfig = targetProfile
|
||||
? dependencies.subscription.readConfig(targetProfile.id)
|
||||
: null;
|
||||
if (!targetServerId || !subscriptionConfig) {
|
||||
if (bypassed || !targetServerId || !subscriptionConfig) {
|
||||
let stateCommitStarted = false;
|
||||
try {
|
||||
stateCommitStarted = true;
|
||||
dependencies.state.update((state) => ({
|
||||
...state,
|
||||
routeRules,
|
||||
...(bypassed ? { appliedRouteRules: [] } : {}),
|
||||
routeRulesRevision: state.routeRulesRevision + 1,
|
||||
}));
|
||||
} catch (error) {
|
||||
@@ -68,14 +74,17 @@ export function createRouteRulesService(dependencies: RouteRulesDependencies) {
|
||||
routeRules,
|
||||
);
|
||||
const previousConfig = dependencies.config.read();
|
||||
const configChanged = previousConfig !== JSON.stringify(candidateConfig, null, 2);
|
||||
let configMutationStarted = false;
|
||||
let runtimeMutationStarted = false;
|
||||
let stateCommitStarted = false;
|
||||
|
||||
try {
|
||||
configMutationStarted = true;
|
||||
dependencies.config.write(candidateConfig);
|
||||
if (wasRunning) {
|
||||
if (configChanged) {
|
||||
configMutationStarted = true;
|
||||
dependencies.config.write(candidateConfig);
|
||||
}
|
||||
if (wasRunning && configChanged) {
|
||||
const command = await dependencies.runtime.applyCommand();
|
||||
runtimeMutationStarted = command.mutationStarted;
|
||||
if (!command.ok) throw command.error;
|
||||
@@ -103,24 +112,27 @@ export function createRouteRulesService(dependencies: RouteRulesDependencies) {
|
||||
}
|
||||
};
|
||||
|
||||
const update = (rules: unknown, expectedRulesRevision: unknown, expectedRevision: unknown) => {
|
||||
const update = (
|
||||
rules: unknown,
|
||||
expectedRulesRevision: unknown,
|
||||
rulesContractVersion: unknown,
|
||||
) => {
|
||||
if (rulesContractVersion !== ROUTE_RULES_CONTRACT_VERSION) {
|
||||
throw new HarborError('REQUEST_INVALID');
|
||||
}
|
||||
let routeRules: RouteRule[];
|
||||
try {
|
||||
routeRules = normalizeRouteRules(rules, { strict: true }) as RouteRule[];
|
||||
} catch (cause) {
|
||||
throw new HarborError('REQUEST_INVALID', { cause });
|
||||
}
|
||||
const rulesRevision = expectedRulesRevision ?? expectedRevision;
|
||||
if (!Number.isSafeInteger(rulesRevision) || Number(rulesRevision) < 0) {
|
||||
if (!Number.isSafeInteger(expectedRulesRevision) || Number(expectedRulesRevision) < 0) {
|
||||
throw new HarborError('REQUEST_INVALID');
|
||||
}
|
||||
|
||||
return dependencies.serialize(async () => {
|
||||
const current = dependencies.state.read();
|
||||
const currentRevision = expectedRulesRevision == null
|
||||
? current.revision
|
||||
: current.routeRulesRevision;
|
||||
if (currentRevision !== rulesRevision) throw new HarborError('STATE_CONFLICT');
|
||||
if (current.routeRulesRevision !== expectedRulesRevision) throw new HarborError('STATE_CONFLICT');
|
||||
if (isDeepStrictEqual(current.routeRules, routeRules)) return;
|
||||
await dependencies.runOperation(() => applyRules(current, routeRules));
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user