feat: add server lifecycle management and D1 logging

- Add start/stop/reboot endpoints for server power management
- Add D1-based logging system (logs table + db-logger utility)
- Add idempotency_key validation for order deduplication
- Extend VPS provider interface with lifecycle methods

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
kappa
2026-01-30 08:27:34 +09:00
parent f62712af37
commit 6385b5cab6
13 changed files with 767 additions and 7 deletions

View File

@@ -134,9 +134,96 @@ export class VultrProvider extends VPSProviderBase {
}
}
async startServer(instanceId: string): Promise<{ success: boolean; error?: string }> {
const url = `${this.config.baseUrl}/instances/${instanceId}/start`;
try {
const response = await this.fetchWithRetry(url, {
method: 'POST',
headers: {
Authorization: `Bearer ${this.config.apiKey}`,
},
});
// Vultr returns 204 No Content on success
if (response.status === 204 || response.ok) {
return { success: true };
}
const error = (await response.json()) as VultrError;
return {
success: false,
error: error.error || 'Failed to start instance',
};
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : 'Network error',
};
}
}
async stopServer(instanceId: string): Promise<{ success: boolean; error?: string }> {
const url = `${this.config.baseUrl}/instances/${instanceId}/halt`;
try {
const response = await this.fetchWithRetry(url, {
method: 'POST',
headers: {
Authorization: `Bearer ${this.config.apiKey}`,
},
});
// Vultr returns 204 No Content on success
if (response.status === 204 || response.ok) {
return { success: true };
}
const error = (await response.json()) as VultrError;
return {
success: false,
error: error.error || 'Failed to stop instance',
};
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : 'Network error',
};
}
}
async rebootServer(instanceId: string): Promise<{ success: boolean; error?: string }> {
const url = `${this.config.baseUrl}/instances/${instanceId}/reboot`;
try {
const response = await this.fetchWithRetry(url, {
method: 'POST',
headers: {
Authorization: `Bearer ${this.config.apiKey}`,
},
});
// Vultr returns 204 No Content on success
if (response.status === 204 || response.ok) {
return { success: true };
}
const error = (await response.json()) as VultrError;
return {
success: false,
error: error.error || 'Failed to reboot instance',
};
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : 'Network error',
};
}
}
async getServerStatus(
instanceId: string
): Promise<{ status: string; ipv4?: string; ipv6?: string }> {
): Promise<{ status: string; power_status?: string; ipv4?: string; ipv6?: string }> {
const url = `${this.config.baseUrl}/instances/${instanceId}`;
try {
@@ -154,6 +241,7 @@ export class VultrProvider extends VPSProviderBase {
const data = (await response.json()) as { instance: VultrInstance };
return {
status: data.instance.status,
power_status: data.instance.power_status,
ipv4: data.instance.main_ip !== '0.0.0.0' ? data.instance.main_ip : undefined,
ipv6: data.instance.v6_main_ip || undefined,
};