Update Docker configuration, enhance error handling, and improve logging
- Added health check to the camera management API service in docker-compose.yml for better container reliability. - Updated installation scripts in Dockerfile to check for existing dependencies before installation, improving efficiency. - Enhanced error handling in the USDAVisionSystem class to allow partial operation if some components fail to start, preventing immediate shutdown. - Improved logging throughout the application, including more detailed error messages and critical error handling in the main loop. - Refactored WebSocketManager and CameraMonitor classes to use debug logging for connection events, reducing log noise.
This commit is contained in:
@@ -80,8 +80,7 @@ export interface MachineType {
|
||||
// Phase-specific interfaces
|
||||
export interface Soaking {
|
||||
id: string
|
||||
experiment_id: string
|
||||
repetition_id?: string | null
|
||||
repetition_id: string
|
||||
scheduled_start_time: string
|
||||
actual_start_time?: string | null
|
||||
soaking_duration_minutes: number
|
||||
@@ -94,8 +93,7 @@ export interface Soaking {
|
||||
|
||||
export interface Airdrying {
|
||||
id: string
|
||||
experiment_id: string
|
||||
repetition_id?: string | null
|
||||
repetition_id: string
|
||||
scheduled_start_time: string
|
||||
actual_start_time?: string | null
|
||||
duration_minutes: number
|
||||
@@ -307,8 +305,7 @@ export interface UpdatePhaseDataRequest {
|
||||
|
||||
// Phase creation request interfaces
|
||||
export interface CreateSoakingRequest {
|
||||
experiment_id: string
|
||||
repetition_id?: string
|
||||
repetition_id: string
|
||||
scheduled_start_time: string
|
||||
soaking_duration_minutes: number
|
||||
actual_start_time?: string
|
||||
@@ -316,19 +313,17 @@ export interface CreateSoakingRequest {
|
||||
}
|
||||
|
||||
export interface CreateAirdryingRequest {
|
||||
experiment_id: string
|
||||
repetition_id?: string
|
||||
scheduled_start_time?: string // Will be auto-calculated from soaking if not provided
|
||||
repetition_id: string
|
||||
scheduled_start_time: string
|
||||
duration_minutes: number
|
||||
actual_start_time?: string
|
||||
actual_end_time?: string
|
||||
}
|
||||
|
||||
export interface CreateCrackingRequest {
|
||||
experiment_id: string
|
||||
repetition_id?: string
|
||||
repetition_id: string
|
||||
machine_type_id: string
|
||||
scheduled_start_time?: string // Will be auto-calculated from airdrying if not provided
|
||||
scheduled_start_time: string
|
||||
actual_start_time?: string
|
||||
actual_end_time?: string
|
||||
}
|
||||
@@ -798,11 +793,22 @@ export const phaseManagement = {
|
||||
const { data: { user }, error: authError } = await supabase.auth.getUser()
|
||||
if (authError || !user) throw new Error('User not authenticated')
|
||||
|
||||
if (!request.repetition_id) {
|
||||
throw new Error('repetition_id is required')
|
||||
}
|
||||
|
||||
const scheduledEndTime = new Date(new Date(request.scheduled_start_time).getTime() + request.soaking_duration_minutes * 60000).toISOString()
|
||||
|
||||
const { data, error } = await supabase
|
||||
.from('soaking')
|
||||
.insert({
|
||||
...request,
|
||||
.upsert({
|
||||
repetition_id: request.repetition_id,
|
||||
scheduled_start_time: request.scheduled_start_time,
|
||||
soaking_duration_minutes: request.soaking_duration_minutes,
|
||||
scheduled_end_time: scheduledEndTime,
|
||||
created_by: user.id
|
||||
}, {
|
||||
onConflict: 'repetition_id'
|
||||
})
|
||||
.select()
|
||||
.single()
|
||||
@@ -824,10 +830,23 @@ export const phaseManagement = {
|
||||
},
|
||||
|
||||
async getSoakingByExperimentId(experimentId: string): Promise<Soaking | null> {
|
||||
// Get the first repetition for this experiment
|
||||
const { data: repetitions, error: repsError } = await supabase
|
||||
.from('experiment_repetitions')
|
||||
.select('id')
|
||||
.eq('experiment_id', experimentId)
|
||||
.order('repetition_number', { ascending: true })
|
||||
.limit(1)
|
||||
|
||||
if (repsError || !repetitions || repetitions.length === 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
// Get soaking for the first repetition
|
||||
const { data, error } = await supabase
|
||||
.from('soaking')
|
||||
.select('*')
|
||||
.eq('experiment_id', experimentId)
|
||||
.eq('repetition_id', repetitions[0].id)
|
||||
.single()
|
||||
|
||||
if (error) {
|
||||
@@ -856,11 +875,26 @@ export const phaseManagement = {
|
||||
const { data: { user }, error: authError } = await supabase.auth.getUser()
|
||||
if (authError || !user) throw new Error('User not authenticated')
|
||||
|
||||
if (!request.repetition_id) {
|
||||
throw new Error('repetition_id is required')
|
||||
}
|
||||
|
||||
if (!request.scheduled_start_time) {
|
||||
throw new Error('scheduled_start_time is required')
|
||||
}
|
||||
|
||||
const scheduledEndTime = new Date(new Date(request.scheduled_start_time).getTime() + request.duration_minutes * 60000).toISOString()
|
||||
|
||||
const { data, error } = await supabase
|
||||
.from('airdrying')
|
||||
.insert({
|
||||
...request,
|
||||
.upsert({
|
||||
repetition_id: request.repetition_id,
|
||||
scheduled_start_time: request.scheduled_start_time,
|
||||
duration_minutes: request.duration_minutes,
|
||||
scheduled_end_time: scheduledEndTime,
|
||||
created_by: user.id
|
||||
}, {
|
||||
onConflict: 'repetition_id'
|
||||
})
|
||||
.select()
|
||||
.single()
|
||||
@@ -882,10 +916,23 @@ export const phaseManagement = {
|
||||
},
|
||||
|
||||
async getAirdryingByExperimentId(experimentId: string): Promise<Airdrying | null> {
|
||||
// Get the first repetition for this experiment
|
||||
const { data: repetitions, error: repsError } = await supabase
|
||||
.from('experiment_repetitions')
|
||||
.select('id')
|
||||
.eq('experiment_id', experimentId)
|
||||
.order('repetition_number', { ascending: true })
|
||||
.limit(1)
|
||||
|
||||
if (repsError || !repetitions || repetitions.length === 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
// Get airdrying for the first repetition
|
||||
const { data, error } = await supabase
|
||||
.from('airdrying')
|
||||
.select('*')
|
||||
.eq('experiment_id', experimentId)
|
||||
.eq('repetition_id', repetitions[0].id)
|
||||
.single()
|
||||
|
||||
if (error) {
|
||||
@@ -914,11 +961,23 @@ export const phaseManagement = {
|
||||
const { data: { user }, error: authError } = await supabase.auth.getUser()
|
||||
if (authError || !user) throw new Error('User not authenticated')
|
||||
|
||||
if (!request.repetition_id) {
|
||||
throw new Error('repetition_id is required')
|
||||
}
|
||||
|
||||
if (!request.scheduled_start_time) {
|
||||
throw new Error('scheduled_start_time is required')
|
||||
}
|
||||
|
||||
const { data, error } = await supabase
|
||||
.from('cracking')
|
||||
.insert({
|
||||
...request,
|
||||
.upsert({
|
||||
repetition_id: request.repetition_id,
|
||||
machine_type_id: request.machine_type_id,
|
||||
scheduled_start_time: request.scheduled_start_time,
|
||||
created_by: user.id
|
||||
}, {
|
||||
onConflict: 'repetition_id'
|
||||
})
|
||||
.select()
|
||||
.single()
|
||||
|
||||
Reference in New Issue
Block a user