2024-08-12 14:18:13 +02:00
package booking
import (
"time"
2025-01-16 10:14:55 +01:00
"cloud.o-forge.io/core/oc-lib/models/common/enum"
2025-06-18 07:58:40 +02:00
"cloud.o-forge.io/core/oc-lib/models/common/models"
2024-08-12 14:18:13 +02:00
"cloud.o-forge.io/core/oc-lib/models/utils"
2024-08-12 16:11:25 +02:00
"cloud.o-forge.io/core/oc-lib/tools"
2024-08-12 14:18:13 +02:00
)
2024-08-30 14:50:48 +02:00
/ *
* Booking is a struct that represents a booking
* /
2024-08-12 14:18:13 +02:00
type Booking struct {
2025-07-08 13:42:13 +02:00
utils . AbstractObject // AbstractObject contains the basic fields of an object (id, name)
PricedItem map [ string ] interface { } ` json:"priced_item,omitempty" bson:"priced_item,omitempty" ` // We need to add the validate:"required" tag once the pricing feature is implemented, removed to avoid handling the error
2025-06-18 07:58:40 +02:00
2025-07-08 13:42:13 +02:00
ResumeMetrics map [ string ] map [ string ] models . MetricResume ` json:"resume_metrics,omitempty" bson:"resume_metrics,omitempty" `
2025-06-18 07:58:40 +02:00
ExecutionMetrics map [ string ] [ ] models . MetricsSnapshot ` json:"metrics,omitempty" bson:"metrics,omitempty" `
ExecutionsID string ` json:"executions_id,omitempty" bson:"executions_id,omitempty" validate:"required" ` // ExecutionsID is the ID of the executions
2026-01-13 16:04:31 +01:00
DestPeerID string ` json:"dest_peer_id,omitempty" bson:"dest_peer_id,omitempty" ` // DestPeerID is the ID of the destination peer
2025-06-18 07:58:40 +02:00
WorkflowID string ` json:"workflow_id,omitempty" bson:"workflow_id,omitempty" ` // WorkflowID is the ID of the workflow
ExecutionID string ` json:"execution_id,omitempty" bson:"execution_id,omitempty" validate:"required" `
2026-03-16 10:49:39 +01:00
State enum . BookingStatus ` json:"state" bson:"state" ` // State is the state of the booking
2025-06-18 07:58:40 +02:00
ExpectedStartDate time . Time ` json:"expected_start_date,omitempty" bson:"expected_start_date,omitempty" validate:"required" ` // ExpectedStartDate is the expected start date of the booking
ExpectedEndDate * time . Time ` json:"expected_end_date,omitempty" bson:"expected_end_date,omitempty" validate:"required" ` // ExpectedEndDate is the expected end date of the booking
2024-12-12 16:25:47 +01:00
RealStartDate * time . Time ` json:"real_start_date,omitempty" bson:"real_start_date,omitempty" ` // RealStartDate is the real start date of the booking
RealEndDate * time . Time ` json:"real_end_date,omitempty" bson:"real_end_date,omitempty" ` // RealEndDate is the real end date of the booking
2025-01-13 12:25:57 +01:00
ResourceType tools . DataType ` json:"resource_type,omitempty" bson:"resource_type,omitempty" validate:"required" ` // ResourceType is the type of the resource
ResourceID string ` json:"resource_id,omitempty" bson:"resource_id,omitempty" validate:"required" ` // could be a Compute or a Storage
2026-02-23 15:08:27 +01:00
InstanceID string ` json:"instance_id,omitempty" bson:"instance_id,omitempty" validate:"required" ` // could be a Compute or a Storage
2026-03-16 08:52:31 +01:00
// Authorization: identifies who created this draft and the Check session it belongs to.
// Used to verify UPDATE and DELETE orders from remote schedulers.
2026-03-17 09:01:47 +01:00
SchedulerPeerID string ` json:"scheduler_peer_id,omitempty" bson:"scheduler_peer_id,omitempty" `
2024-08-12 14:18:13 +02:00
}
2025-06-18 07:58:40 +02:00
func ( b * Booking ) CalcDeltaOfExecution ( ) map [ string ] map [ string ] models . MetricResume {
m := map [ string ] map [ string ] models . MetricResume { }
for instance , snapshot := range b . ExecutionMetrics {
m [ instance ] = map [ string ] models . MetricResume { }
for _ , metric := range snapshot {
for _ , mm := range metric . Metrics {
if resume , ok := m [ instance ] [ mm . Name ] ; ! ok {
m [ instance ] [ mm . Name ] = models . MetricResume {
Delta : 0 ,
LastValue : mm . Value ,
}
} else {
delta := resume . LastValue - mm . Value
if delta == 0 {
resume . Delta = delta
} else {
resume . Delta = ( resume . Delta + delta ) / 2
}
resume . LastValue = mm . Value
m [ instance ] [ mm . Name ] = resume
}
}
}
}
return m
}
2024-12-12 16:25:47 +01:00
func ( d * Booking ) GetDelayForLaunch ( ) time . Duration {
return d . RealStartDate . Sub ( d . ExpectedStartDate )
}
func ( d * Booking ) GetDelayForFinishing ( ) time . Duration {
2026-03-20 16:14:07 +01:00
if d . ExpectedEndDate == nil || d . RealEndDate == nil {
2024-12-12 16:25:47 +01:00
return time . Duration ( 0 )
}
2026-03-20 16:14:07 +01:00
return d . RealEndDate . Sub ( * d . ExpectedEndDate )
2024-08-12 14:18:13 +02:00
}
2024-12-12 16:25:47 +01:00
func ( d * Booking ) GetUsualDuration ( ) time . Duration {
return d . ExpectedEndDate . Sub ( d . ExpectedStartDate )
}
func ( d * Booking ) GetRealDuration ( ) time . Duration {
if d . RealEndDate == nil || d . RealStartDate == nil {
return time . Duration ( 0 )
}
return d . RealEndDate . Sub ( * d . RealStartDate )
}
func ( d * Booking ) GetDelayOnDuration ( ) time . Duration {
return d . GetRealDuration ( ) - d . GetUsualDuration ( )
2024-08-12 14:18:13 +02:00
}
2024-12-12 16:25:47 +01:00
func ( d * Booking ) GetAccessor ( request * tools . APIRequest ) utils . Accessor {
return NewAccessor ( request ) // Create a new instance of the accessor
2024-08-12 14:18:13 +02:00
}
2024-12-04 12:14:55 +01:00
2026-01-13 16:04:31 +01:00
func ( d * Booking ) VerifyAuth ( callName string , request * tools . APIRequest ) bool {
2024-12-04 12:14:55 +01:00
return true
}
2024-12-12 16:25:47 +01:00
func ( r * Booking ) StoreDraftDefault ( ) {
2026-03-16 10:59:31 +01:00
r . IsDraft = true
r . State = enum . DRAFT
2024-12-12 16:25:47 +01:00
}
func ( r * Booking ) CanUpdate ( set utils . DBObject ) ( bool , utils . DBObject ) {
2026-03-20 16:14:07 +01:00
incoming := set . ( * Booking )
if ! r . IsDraft && r . State != incoming . State || r . RealStartDate != incoming . RealStartDate || r . RealEndDate != incoming . RealEndDate {
patch := & Booking {
State : incoming . State ,
RealStartDate : incoming . RealStartDate ,
RealEndDate : incoming . RealEndDate ,
}
// Auto-set RealStartDate when transitioning to STARTED and not already set
if r . State != enum . STARTED && incoming . State == enum . STARTED && patch . RealStartDate == nil {
now := time . Now ( )
patch . RealStartDate = & now
}
return true , patch
2024-12-12 16:25:47 +01:00
}
return r . IsDraft , set
}
func ( r * Booking ) CanDelete ( ) bool {
return r . IsDraft // only draft bookings can be deleted
}