xc-mcp
Version:
MCP server that wraps Xcode command-line tools for iOS/macOS development workflows
146 lines • 4.67 kB
JavaScript
/**
* Enhanced Simulator Lifecycle State Management
*
* Tracks state transitions and prevents race conditions in concurrent operations
*/
export var SimulatorState;
(function (SimulatorState) {
SimulatorState["Unknown"] = "Unknown";
SimulatorState["Creating"] = "Creating";
SimulatorState["Booting"] = "Booting";
SimulatorState["Booted"] = "Booted";
SimulatorState["Shutting"] = "Shutting";
SimulatorState["Shutdown"] = "Shutdown";
SimulatorState["Erasing"] = "Erasing";
SimulatorState["Erased"] = "Erased";
})(SimulatorState || (SimulatorState = {}));
export class EnhancedSimulatorLifecycle {
simulatorStates = new Map();
stateTransitions = new Map();
operationQueues = new Map();
bootingPromises = new Map();
transitionLocks = new Map();
/**
* Get current simulator state
*/
getState(udid) {
return this.simulatorStates.get(udid) || SimulatorState.Unknown;
}
/**
* Record a state transition
*/
recordTransition(udid, from, to, operation, success, error) {
const transitions = this.stateTransitions.get(udid) || [];
const lastTransition = transitions[transitions.length - 1];
const duration = lastTransition ? Date.now() - lastTransition.timestamp : undefined;
const transition = {
fromState: from,
toState: to,
operation,
timestamp: Date.now(),
duration,
success,
error,
};
transitions.push(transition);
this.stateTransitions.set(udid, transitions);
this.simulatorStates.set(udid, to);
}
/**
* Get state transition history
*/
getTransitionHistory(udid) {
return this.stateTransitions.get(udid) || [];
}
/**
* Queue an operation for a simulator
*/
queueOperation(udid, operationId, operation) {
const queue = this.operationQueues.get(udid) || [];
queue.push({
operationId,
operation,
startTime: Date.now(),
simulator: udid,
});
this.operationQueues.set(udid, queue);
}
/**
* Get pending operations for simulator
*/
getPendingOperations(udid) {
return this.operationQueues.get(udid) || [];
}
/**
* Clear pending operations
*/
clearPendingOperations(udid) {
this.operationQueues.delete(udid);
}
/**
* Wait for boot to complete
*/
async waitForBoot(udid) {
const existing = this.bootingPromises.get(udid);
if (existing) {
return existing;
}
// Create new promise
const bootPromise = new Promise(resolve => {
// Resolve immediately if already booted
if (this.simulatorStates.get(udid) === SimulatorState.Booted) {
resolve();
}
// Poll for boot completion (max 5 minutes)
const startTime = Date.now();
const checkInterval = setInterval(() => {
if (this.simulatorStates.get(udid) === SimulatorState.Booted) {
clearInterval(checkInterval);
resolve();
}
if (Date.now() - startTime > 5 * 60 * 1000) {
clearInterval(checkInterval);
resolve(); // Timeout - assume booted
}
}, 500);
});
this.bootingPromises.set(udid, bootPromise);
return bootPromise;
}
/**
* Prevent concurrent operations of same type on same simulator
*/
acquireLock(udid) {
if (this.transitionLocks.get(udid)) {
return false; // Already locked
}
this.transitionLocks.set(udid, true);
return true;
}
/**
* Release lock
*/
releaseLock(udid) {
this.transitionLocks.delete(udid);
}
/**
* Get lifecycle summary
*/
getSummary(udid) {
const state = this.simulatorStates.get(udid);
const transitions = this.stateTransitions.get(udid) || [];
const pendingOps = this.operationQueues.get(udid) || [];
return {
udid,
currentState: state,
transitionCount: transitions.length,
lastTransition: transitions[transitions.length - 1],
pendingOperations: pendingOps.length,
operations: pendingOps,
isLocked: this.transitionLocks.has(udid),
};
}
}
// Singleton instance
export const enhancedSimulatorLifecycle = new EnhancedSimulatorLifecycle();
//# sourceMappingURL=simulator-lifecycle-enhanced.js.map