From 97d567785fb35b78ec33c6ae3cb0746b2fac4bf7 Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Thu, 22 May 2025 09:40:27 +0200 Subject: [PATCH 01/25] [core] update odc.proto to include collection info OCTRL-1024 --- core/integration/odc/protos/odc.pb.go | 405 ++++++++++++++++---------- core/integration/odc/protos/odc.proto | 13 +- 2 files changed, 265 insertions(+), 153 deletions(-) diff --git a/core/integration/odc/protos/odc.pb.go b/core/integration/odc/protos/odc.pb.go index 4edcb3cc5..9475e2b02 100644 --- a/core/integration/odc/protos/odc.pb.go +++ b/core/integration/odc/protos/odc.pb.go @@ -394,6 +394,78 @@ func (x *Device) GetRmsjobid() string { return "" } +// Collection information +type Collection struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id uint64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` // Runtime collection ID (same as in DDS) + State string `protobuf:"bytes,2,opt,name=state,proto3" json:"state,omitempty"` // Aggregated state as string + Path string `protobuf:"bytes,3,opt,name=path,proto3" json:"path,omitempty"` // Path in the topology + Host string `protobuf:"bytes,5,opt,name=host,proto3" json:"host,omitempty"` // Host where the collection runs +} + +func (x *Collection) Reset() { + *x = Collection{} + if protoimpl.UnsafeEnabled { + mi := &file_protos_odc_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Collection) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Collection) ProtoMessage() {} + +func (x *Collection) ProtoReflect() protoreflect.Message { + mi := &file_protos_odc_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Collection.ProtoReflect.Descriptor instead. +func (*Collection) Descriptor() ([]byte, []int) { + return file_protos_odc_proto_rawDescGZIP(), []int{3} +} + +func (x *Collection) GetId() uint64 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *Collection) GetState() string { + if x != nil { + return x.State + } + return "" +} + +func (x *Collection) GetPath() string { + if x != nil { + return x.Path + } + return "" +} + +func (x *Collection) GetHost() string { + if x != nil { + return x.Host + } + return "" +} + // Device change/get state request type StateRequest struct { state protoimpl.MessageState @@ -410,7 +482,7 @@ type StateRequest struct { func (x *StateRequest) Reset() { *x = StateRequest{} if protoimpl.UnsafeEnabled { - mi := &file_protos_odc_proto_msgTypes[3] + mi := &file_protos_odc_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -423,7 +495,7 @@ func (x *StateRequest) String() string { func (*StateRequest) ProtoMessage() {} func (x *StateRequest) ProtoReflect() protoreflect.Message { - mi := &file_protos_odc_proto_msgTypes[3] + mi := &file_protos_odc_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -436,7 +508,7 @@ func (x *StateRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use StateRequest.ProtoReflect.Descriptor instead. func (*StateRequest) Descriptor() ([]byte, []int) { - return file_protos_odc_proto_rawDescGZIP(), []int{3} + return file_protos_odc_proto_rawDescGZIP(), []int{4} } func (x *StateRequest) GetPartitionid() string { @@ -480,14 +552,15 @@ type StateReply struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Reply *GeneralReply `protobuf:"bytes,1,opt,name=reply,proto3" json:"reply,omitempty"` // General reply. See GeneralReply message for details. - Devices []*Device `protobuf:"bytes,2,rep,name=devices,proto3" json:"devices,omitempty"` // If detailed reply is requested then this field contains a list of affected devices otherwise it's empty. + Reply *GeneralReply `protobuf:"bytes,1,opt,name=reply,proto3" json:"reply,omitempty"` // General reply. See GeneralReply message for details. + Devices []*Device `protobuf:"bytes,2,rep,name=devices,proto3" json:"devices,omitempty"` // If detailed reply is requested then this field contains a list of affected devices otherwise it's empty. + Collections []*Collection `protobuf:"bytes,3,rep,name=collections,proto3" json:"collections,omitempty"` // If detailed reply is requested then this field contains a list of affected collections otherwise it's empty. } func (x *StateReply) Reset() { *x = StateReply{} if protoimpl.UnsafeEnabled { - mi := &file_protos_odc_proto_msgTypes[4] + mi := &file_protos_odc_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -500,7 +573,7 @@ func (x *StateReply) String() string { func (*StateReply) ProtoMessage() {} func (x *StateReply) ProtoReflect() protoreflect.Message { - mi := &file_protos_odc_proto_msgTypes[4] + mi := &file_protos_odc_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -513,7 +586,7 @@ func (x *StateReply) ProtoReflect() protoreflect.Message { // Deprecated: Use StateReply.ProtoReflect.Descriptor instead. func (*StateReply) Descriptor() ([]byte, []int) { - return file_protos_odc_proto_rawDescGZIP(), []int{4} + return file_protos_odc_proto_rawDescGZIP(), []int{5} } func (x *StateReply) GetReply() *GeneralReply { @@ -530,6 +603,13 @@ func (x *StateReply) GetDevices() []*Device { return nil } +func (x *StateReply) GetCollections() []*Collection { + if x != nil { + return x.Collections + } + return nil +} + // Status of each partition type PartitionStatus struct { state protoimpl.MessageState @@ -547,7 +627,7 @@ type PartitionStatus struct { func (x *PartitionStatus) Reset() { *x = PartitionStatus{} if protoimpl.UnsafeEnabled { - mi := &file_protos_odc_proto_msgTypes[5] + mi := &file_protos_odc_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -560,7 +640,7 @@ func (x *PartitionStatus) String() string { func (*PartitionStatus) ProtoMessage() {} func (x *PartitionStatus) ProtoReflect() protoreflect.Message { - mi := &file_protos_odc_proto_msgTypes[5] + mi := &file_protos_odc_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -573,7 +653,7 @@ func (x *PartitionStatus) ProtoReflect() protoreflect.Message { // Deprecated: Use PartitionStatus.ProtoReflect.Descriptor instead. func (*PartitionStatus) Descriptor() ([]byte, []int) { - return file_protos_odc_proto_rawDescGZIP(), []int{5} + return file_protos_odc_proto_rawDescGZIP(), []int{6} } func (x *PartitionStatus) GetPartitionid() string { @@ -634,7 +714,7 @@ type StatusReply struct { func (x *StatusReply) Reset() { *x = StatusReply{} if protoimpl.UnsafeEnabled { - mi := &file_protos_odc_proto_msgTypes[6] + mi := &file_protos_odc_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -647,7 +727,7 @@ func (x *StatusReply) String() string { func (*StatusReply) ProtoMessage() {} func (x *StatusReply) ProtoReflect() protoreflect.Message { - mi := &file_protos_odc_proto_msgTypes[6] + mi := &file_protos_odc_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -660,7 +740,7 @@ func (x *StatusReply) ProtoReflect() protoreflect.Message { // Deprecated: Use StatusReply.ProtoReflect.Descriptor instead. func (*StatusReply) Descriptor() ([]byte, []int) { - return file_protos_odc_proto_rawDescGZIP(), []int{6} + return file_protos_odc_proto_rawDescGZIP(), []int{7} } func (x *StatusReply) GetMsg() string { @@ -713,7 +793,7 @@ type InitializeRequest struct { func (x *InitializeRequest) Reset() { *x = InitializeRequest{} if protoimpl.UnsafeEnabled { - mi := &file_protos_odc_proto_msgTypes[7] + mi := &file_protos_odc_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -726,7 +806,7 @@ func (x *InitializeRequest) String() string { func (*InitializeRequest) ProtoMessage() {} func (x *InitializeRequest) ProtoReflect() protoreflect.Message { - mi := &file_protos_odc_proto_msgTypes[7] + mi := &file_protos_odc_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -739,7 +819,7 @@ func (x *InitializeRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use InitializeRequest.ProtoReflect.Descriptor instead. func (*InitializeRequest) Descriptor() ([]byte, []int) { - return file_protos_odc_proto_rawDescGZIP(), []int{7} + return file_protos_odc_proto_rawDescGZIP(), []int{8} } func (x *InitializeRequest) GetPartitionid() string { @@ -786,7 +866,7 @@ type SubmitRequest struct { func (x *SubmitRequest) Reset() { *x = SubmitRequest{} if protoimpl.UnsafeEnabled { - mi := &file_protos_odc_proto_msgTypes[8] + mi := &file_protos_odc_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -799,7 +879,7 @@ func (x *SubmitRequest) String() string { func (*SubmitRequest) ProtoMessage() {} func (x *SubmitRequest) ProtoReflect() protoreflect.Message { - mi := &file_protos_odc_proto_msgTypes[8] + mi := &file_protos_odc_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -812,7 +892,7 @@ func (x *SubmitRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SubmitRequest.ProtoReflect.Descriptor instead. func (*SubmitRequest) Descriptor() ([]byte, []int) { - return file_protos_odc_proto_rawDescGZIP(), []int{8} + return file_protos_odc_proto_rawDescGZIP(), []int{9} } func (x *SubmitRequest) GetPartitionid() string { @@ -868,7 +948,7 @@ type ActivateRequest struct { func (x *ActivateRequest) Reset() { *x = ActivateRequest{} if protoimpl.UnsafeEnabled { - mi := &file_protos_odc_proto_msgTypes[9] + mi := &file_protos_odc_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -881,7 +961,7 @@ func (x *ActivateRequest) String() string { func (*ActivateRequest) ProtoMessage() {} func (x *ActivateRequest) ProtoReflect() protoreflect.Message { - mi := &file_protos_odc_proto_msgTypes[9] + mi := &file_protos_odc_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -894,7 +974,7 @@ func (x *ActivateRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ActivateRequest.ProtoReflect.Descriptor instead. func (*ActivateRequest) Descriptor() ([]byte, []int) { - return file_protos_odc_proto_rawDescGZIP(), []int{9} + return file_protos_odc_proto_rawDescGZIP(), []int{10} } func (x *ActivateRequest) GetPartitionid() string { @@ -960,7 +1040,7 @@ type RunRequest struct { func (x *RunRequest) Reset() { *x = RunRequest{} if protoimpl.UnsafeEnabled { - mi := &file_protos_odc_proto_msgTypes[10] + mi := &file_protos_odc_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -973,7 +1053,7 @@ func (x *RunRequest) String() string { func (*RunRequest) ProtoMessage() {} func (x *RunRequest) ProtoReflect() protoreflect.Message { - mi := &file_protos_odc_proto_msgTypes[10] + mi := &file_protos_odc_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -986,7 +1066,7 @@ func (x *RunRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RunRequest.ProtoReflect.Descriptor instead. func (*RunRequest) Descriptor() ([]byte, []int) { - return file_protos_odc_proto_rawDescGZIP(), []int{10} + return file_protos_odc_proto_rawDescGZIP(), []int{11} } func (x *RunRequest) GetPartitionid() string { @@ -1070,7 +1150,7 @@ type UpdateRequest struct { func (x *UpdateRequest) Reset() { *x = UpdateRequest{} if protoimpl.UnsafeEnabled { - mi := &file_protos_odc_proto_msgTypes[11] + mi := &file_protos_odc_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1083,7 +1163,7 @@ func (x *UpdateRequest) String() string { func (*UpdateRequest) ProtoMessage() {} func (x *UpdateRequest) ProtoReflect() protoreflect.Message { - mi := &file_protos_odc_proto_msgTypes[11] + mi := &file_protos_odc_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1096,7 +1176,7 @@ func (x *UpdateRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateRequest.ProtoReflect.Descriptor instead. func (*UpdateRequest) Descriptor() ([]byte, []int) { - return file_protos_odc_proto_rawDescGZIP(), []int{11} + return file_protos_odc_proto_rawDescGZIP(), []int{12} } func (x *UpdateRequest) GetPartitionid() string { @@ -1155,7 +1235,7 @@ type ShutdownRequest struct { func (x *ShutdownRequest) Reset() { *x = ShutdownRequest{} if protoimpl.UnsafeEnabled { - mi := &file_protos_odc_proto_msgTypes[12] + mi := &file_protos_odc_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1168,7 +1248,7 @@ func (x *ShutdownRequest) String() string { func (*ShutdownRequest) ProtoMessage() {} func (x *ShutdownRequest) ProtoReflect() protoreflect.Message { - mi := &file_protos_odc_proto_msgTypes[12] + mi := &file_protos_odc_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1181,7 +1261,7 @@ func (x *ShutdownRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ShutdownRequest.ProtoReflect.Descriptor instead. func (*ShutdownRequest) Descriptor() ([]byte, []int) { - return file_protos_odc_proto_rawDescGZIP(), []int{12} + return file_protos_odc_proto_rawDescGZIP(), []int{13} } func (x *ShutdownRequest) GetPartitionid() string { @@ -1218,7 +1298,7 @@ type Property struct { func (x *Property) Reset() { *x = Property{} if protoimpl.UnsafeEnabled { - mi := &file_protos_odc_proto_msgTypes[13] + mi := &file_protos_odc_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1231,7 +1311,7 @@ func (x *Property) String() string { func (*Property) ProtoMessage() {} func (x *Property) ProtoReflect() protoreflect.Message { - mi := &file_protos_odc_proto_msgTypes[13] + mi := &file_protos_odc_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1244,7 +1324,7 @@ func (x *Property) ProtoReflect() protoreflect.Message { // Deprecated: Use Property.ProtoReflect.Descriptor instead. func (*Property) Descriptor() ([]byte, []int) { - return file_protos_odc_proto_rawDescGZIP(), []int{13} + return file_protos_odc_proto_rawDescGZIP(), []int{14} } func (x *Property) GetKey() string { @@ -1277,7 +1357,7 @@ type SetPropertiesRequest struct { func (x *SetPropertiesRequest) Reset() { *x = SetPropertiesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_protos_odc_proto_msgTypes[14] + mi := &file_protos_odc_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1290,7 +1370,7 @@ func (x *SetPropertiesRequest) String() string { func (*SetPropertiesRequest) ProtoMessage() {} func (x *SetPropertiesRequest) ProtoReflect() protoreflect.Message { - mi := &file_protos_odc_proto_msgTypes[14] + mi := &file_protos_odc_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1303,7 +1383,7 @@ func (x *SetPropertiesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetPropertiesRequest.ProtoReflect.Descriptor instead. func (*SetPropertiesRequest) Descriptor() ([]byte, []int) { - return file_protos_odc_proto_rawDescGZIP(), []int{14} + return file_protos_odc_proto_rawDescGZIP(), []int{15} } func (x *SetPropertiesRequest) GetPartitionid() string { @@ -1353,7 +1433,7 @@ type ConfigureRequest struct { func (x *ConfigureRequest) Reset() { *x = ConfigureRequest{} if protoimpl.UnsafeEnabled { - mi := &file_protos_odc_proto_msgTypes[15] + mi := &file_protos_odc_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1366,7 +1446,7 @@ func (x *ConfigureRequest) String() string { func (*ConfigureRequest) ProtoMessage() {} func (x *ConfigureRequest) ProtoReflect() protoreflect.Message { - mi := &file_protos_odc_proto_msgTypes[15] + mi := &file_protos_odc_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1379,7 +1459,7 @@ func (x *ConfigureRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ConfigureRequest.ProtoReflect.Descriptor instead. func (*ConfigureRequest) Descriptor() ([]byte, []int) { - return file_protos_odc_proto_rawDescGZIP(), []int{15} + return file_protos_odc_proto_rawDescGZIP(), []int{16} } func (x *ConfigureRequest) GetRequest() *StateRequest { @@ -1401,7 +1481,7 @@ type StartRequest struct { func (x *StartRequest) Reset() { *x = StartRequest{} if protoimpl.UnsafeEnabled { - mi := &file_protos_odc_proto_msgTypes[16] + mi := &file_protos_odc_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1414,7 +1494,7 @@ func (x *StartRequest) String() string { func (*StartRequest) ProtoMessage() {} func (x *StartRequest) ProtoReflect() protoreflect.Message { - mi := &file_protos_odc_proto_msgTypes[16] + mi := &file_protos_odc_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1427,7 +1507,7 @@ func (x *StartRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use StartRequest.ProtoReflect.Descriptor instead. func (*StartRequest) Descriptor() ([]byte, []int) { - return file_protos_odc_proto_rawDescGZIP(), []int{16} + return file_protos_odc_proto_rawDescGZIP(), []int{17} } func (x *StartRequest) GetRequest() *StateRequest { @@ -1449,7 +1529,7 @@ type StopRequest struct { func (x *StopRequest) Reset() { *x = StopRequest{} if protoimpl.UnsafeEnabled { - mi := &file_protos_odc_proto_msgTypes[17] + mi := &file_protos_odc_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1462,7 +1542,7 @@ func (x *StopRequest) String() string { func (*StopRequest) ProtoMessage() {} func (x *StopRequest) ProtoReflect() protoreflect.Message { - mi := &file_protos_odc_proto_msgTypes[17] + mi := &file_protos_odc_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1475,7 +1555,7 @@ func (x *StopRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use StopRequest.ProtoReflect.Descriptor instead. func (*StopRequest) Descriptor() ([]byte, []int) { - return file_protos_odc_proto_rawDescGZIP(), []int{17} + return file_protos_odc_proto_rawDescGZIP(), []int{18} } func (x *StopRequest) GetRequest() *StateRequest { @@ -1497,7 +1577,7 @@ type ResetRequest struct { func (x *ResetRequest) Reset() { *x = ResetRequest{} if protoimpl.UnsafeEnabled { - mi := &file_protos_odc_proto_msgTypes[18] + mi := &file_protos_odc_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1510,7 +1590,7 @@ func (x *ResetRequest) String() string { func (*ResetRequest) ProtoMessage() {} func (x *ResetRequest) ProtoReflect() protoreflect.Message { - mi := &file_protos_odc_proto_msgTypes[18] + mi := &file_protos_odc_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1523,7 +1603,7 @@ func (x *ResetRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ResetRequest.ProtoReflect.Descriptor instead. func (*ResetRequest) Descriptor() ([]byte, []int) { - return file_protos_odc_proto_rawDescGZIP(), []int{18} + return file_protos_odc_proto_rawDescGZIP(), []int{19} } func (x *ResetRequest) GetRequest() *StateRequest { @@ -1545,7 +1625,7 @@ type TerminateRequest struct { func (x *TerminateRequest) Reset() { *x = TerminateRequest{} if protoimpl.UnsafeEnabled { - mi := &file_protos_odc_proto_msgTypes[19] + mi := &file_protos_odc_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1558,7 +1638,7 @@ func (x *TerminateRequest) String() string { func (*TerminateRequest) ProtoMessage() {} func (x *TerminateRequest) ProtoReflect() protoreflect.Message { - mi := &file_protos_odc_proto_msgTypes[19] + mi := &file_protos_odc_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1571,7 +1651,7 @@ func (x *TerminateRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use TerminateRequest.ProtoReflect.Descriptor instead. func (*TerminateRequest) Descriptor() ([]byte, []int) { - return file_protos_odc_proto_rawDescGZIP(), []int{19} + return file_protos_odc_proto_rawDescGZIP(), []int{20} } func (x *TerminateRequest) GetRequest() *StateRequest { @@ -1593,7 +1673,7 @@ type StatusRequest struct { func (x *StatusRequest) Reset() { *x = StatusRequest{} if protoimpl.UnsafeEnabled { - mi := &file_protos_odc_proto_msgTypes[20] + mi := &file_protos_odc_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1606,7 +1686,7 @@ func (x *StatusRequest) String() string { func (*StatusRequest) ProtoMessage() {} func (x *StatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_protos_odc_proto_msgTypes[20] + mi := &file_protos_odc_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1619,7 +1699,7 @@ func (x *StatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use StatusRequest.ProtoReflect.Descriptor instead. func (*StatusRequest) Descriptor() ([]byte, []int) { - return file_protos_odc_proto_rawDescGZIP(), []int{20} + return file_protos_odc_proto_rawDescGZIP(), []int{21} } func (x *StatusRequest) GetRunning() bool { @@ -1666,21 +1746,30 @@ var file_protos_odc_proto_rawDesc = []byte{ 0x6c, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x6d, 0x73, 0x6a, 0x6f, 0x62, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x6d, 0x73, 0x6a, 0x6f, 0x62, 0x69, 0x64, - 0x22, 0x90, 0x01, 0x0a, 0x0c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, - 0x6e, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x75, 0x6e, 0x6e, 0x72, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x05, 0x72, 0x75, 0x6e, 0x6e, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, - 0x65, 0x6f, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, - 0x6f, 0x75, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x74, 0x61, 0x69, - 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x64, 0x65, 0x74, 0x61, 0x69, - 0x6c, 0x65, 0x64, 0x22, 0x5c, 0x0a, 0x0a, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6c, - 0x79, 0x12, 0x27, 0x0a, 0x05, 0x72, 0x65, 0x70, 0x6c, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x11, 0x2e, 0x6f, 0x64, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x52, 0x65, - 0x70, 0x6c, 0x79, 0x52, 0x05, 0x72, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x25, 0x0a, 0x07, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x6f, 0x64, - 0x63, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x22, 0x5a, 0x0a, 0x0a, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, + 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x22, 0x90, 0x01, 0x0a, + 0x0c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, + 0x0b, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x69, 0x64, 0x12, + 0x14, 0x0a, 0x05, 0x72, 0x75, 0x6e, 0x6e, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, + 0x72, 0x75, 0x6e, 0x6e, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, + 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, + 0x61, 0x74, 0x68, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x22, + 0x8f, 0x01, 0x0a, 0x0a, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x27, + 0x0a, 0x05, 0x72, 0x65, 0x70, 0x6c, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, + 0x6f, 0x64, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x52, 0x65, 0x70, 0x6c, 0x79, + 0x52, 0x05, 0x72, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x25, 0x0a, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x6f, 0x64, 0x63, 0x2e, 0x44, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x31, + 0x0a, 0x0b, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x6f, 0x64, 0x63, 0x2e, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xc3, 0x01, 0x0a, 0x0f, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x72, 0x74, @@ -1879,80 +1968,82 @@ func file_protos_odc_proto_rawDescGZIP() []byte { } var file_protos_odc_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_protos_odc_proto_msgTypes = make([]protoimpl.MessageInfo, 21) +var file_protos_odc_proto_msgTypes = make([]protoimpl.MessageInfo, 22) var file_protos_odc_proto_goTypes = []interface{}{ (ReplyStatus)(0), // 0: odc.ReplyStatus (SessionStatus)(0), // 1: odc.SessionStatus (*Error)(nil), // 2: odc.Error (*GeneralReply)(nil), // 3: odc.GeneralReply (*Device)(nil), // 4: odc.Device - (*StateRequest)(nil), // 5: odc.StateRequest - (*StateReply)(nil), // 6: odc.StateReply - (*PartitionStatus)(nil), // 7: odc.PartitionStatus - (*StatusReply)(nil), // 8: odc.StatusReply - (*InitializeRequest)(nil), // 9: odc.InitializeRequest - (*SubmitRequest)(nil), // 10: odc.SubmitRequest - (*ActivateRequest)(nil), // 11: odc.ActivateRequest - (*RunRequest)(nil), // 12: odc.RunRequest - (*UpdateRequest)(nil), // 13: odc.UpdateRequest - (*ShutdownRequest)(nil), // 14: odc.ShutdownRequest - (*Property)(nil), // 15: odc.Property - (*SetPropertiesRequest)(nil), // 16: odc.SetPropertiesRequest - (*ConfigureRequest)(nil), // 17: odc.ConfigureRequest - (*StartRequest)(nil), // 18: odc.StartRequest - (*StopRequest)(nil), // 19: odc.StopRequest - (*ResetRequest)(nil), // 20: odc.ResetRequest - (*TerminateRequest)(nil), // 21: odc.TerminateRequest - (*StatusRequest)(nil), // 22: odc.StatusRequest + (*Collection)(nil), // 5: odc.Collection + (*StateRequest)(nil), // 6: odc.StateRequest + (*StateReply)(nil), // 7: odc.StateReply + (*PartitionStatus)(nil), // 8: odc.PartitionStatus + (*StatusReply)(nil), // 9: odc.StatusReply + (*InitializeRequest)(nil), // 10: odc.InitializeRequest + (*SubmitRequest)(nil), // 11: odc.SubmitRequest + (*ActivateRequest)(nil), // 12: odc.ActivateRequest + (*RunRequest)(nil), // 13: odc.RunRequest + (*UpdateRequest)(nil), // 14: odc.UpdateRequest + (*ShutdownRequest)(nil), // 15: odc.ShutdownRequest + (*Property)(nil), // 16: odc.Property + (*SetPropertiesRequest)(nil), // 17: odc.SetPropertiesRequest + (*ConfigureRequest)(nil), // 18: odc.ConfigureRequest + (*StartRequest)(nil), // 19: odc.StartRequest + (*StopRequest)(nil), // 20: odc.StopRequest + (*ResetRequest)(nil), // 21: odc.ResetRequest + (*TerminateRequest)(nil), // 22: odc.TerminateRequest + (*StatusRequest)(nil), // 23: odc.StatusRequest } var file_protos_odc_proto_depIdxs = []int32{ 0, // 0: odc.GeneralReply.status:type_name -> odc.ReplyStatus 2, // 1: odc.GeneralReply.error:type_name -> odc.Error 3, // 2: odc.StateReply.reply:type_name -> odc.GeneralReply 4, // 3: odc.StateReply.devices:type_name -> odc.Device - 1, // 4: odc.PartitionStatus.status:type_name -> odc.SessionStatus - 0, // 5: odc.StatusReply.status:type_name -> odc.ReplyStatus - 2, // 6: odc.StatusReply.error:type_name -> odc.Error - 7, // 7: odc.StatusReply.partitions:type_name -> odc.PartitionStatus - 15, // 8: odc.SetPropertiesRequest.properties:type_name -> odc.Property - 5, // 9: odc.ConfigureRequest.request:type_name -> odc.StateRequest - 5, // 10: odc.StartRequest.request:type_name -> odc.StateRequest - 5, // 11: odc.StopRequest.request:type_name -> odc.StateRequest - 5, // 12: odc.ResetRequest.request:type_name -> odc.StateRequest - 5, // 13: odc.TerminateRequest.request:type_name -> odc.StateRequest - 9, // 14: odc.ODC.Initialize:input_type -> odc.InitializeRequest - 10, // 15: odc.ODC.Submit:input_type -> odc.SubmitRequest - 11, // 16: odc.ODC.Activate:input_type -> odc.ActivateRequest - 12, // 17: odc.ODC.Run:input_type -> odc.RunRequest - 13, // 18: odc.ODC.Update:input_type -> odc.UpdateRequest - 17, // 19: odc.ODC.Configure:input_type -> odc.ConfigureRequest - 16, // 20: odc.ODC.SetProperties:input_type -> odc.SetPropertiesRequest - 5, // 21: odc.ODC.GetState:input_type -> odc.StateRequest - 18, // 22: odc.ODC.Start:input_type -> odc.StartRequest - 19, // 23: odc.ODC.Stop:input_type -> odc.StopRequest - 20, // 24: odc.ODC.Reset:input_type -> odc.ResetRequest - 21, // 25: odc.ODC.Terminate:input_type -> odc.TerminateRequest - 14, // 26: odc.ODC.Shutdown:input_type -> odc.ShutdownRequest - 22, // 27: odc.ODC.Status:input_type -> odc.StatusRequest - 3, // 28: odc.ODC.Initialize:output_type -> odc.GeneralReply - 3, // 29: odc.ODC.Submit:output_type -> odc.GeneralReply - 3, // 30: odc.ODC.Activate:output_type -> odc.GeneralReply - 3, // 31: odc.ODC.Run:output_type -> odc.GeneralReply - 3, // 32: odc.ODC.Update:output_type -> odc.GeneralReply - 6, // 33: odc.ODC.Configure:output_type -> odc.StateReply - 3, // 34: odc.ODC.SetProperties:output_type -> odc.GeneralReply - 6, // 35: odc.ODC.GetState:output_type -> odc.StateReply - 6, // 36: odc.ODC.Start:output_type -> odc.StateReply - 6, // 37: odc.ODC.Stop:output_type -> odc.StateReply - 6, // 38: odc.ODC.Reset:output_type -> odc.StateReply - 6, // 39: odc.ODC.Terminate:output_type -> odc.StateReply - 3, // 40: odc.ODC.Shutdown:output_type -> odc.GeneralReply - 8, // 41: odc.ODC.Status:output_type -> odc.StatusReply - 28, // [28:42] is the sub-list for method output_type - 14, // [14:28] is the sub-list for method input_type - 14, // [14:14] is the sub-list for extension type_name - 14, // [14:14] is the sub-list for extension extendee - 0, // [0:14] is the sub-list for field type_name + 5, // 4: odc.StateReply.collections:type_name -> odc.Collection + 1, // 5: odc.PartitionStatus.status:type_name -> odc.SessionStatus + 0, // 6: odc.StatusReply.status:type_name -> odc.ReplyStatus + 2, // 7: odc.StatusReply.error:type_name -> odc.Error + 8, // 8: odc.StatusReply.partitions:type_name -> odc.PartitionStatus + 16, // 9: odc.SetPropertiesRequest.properties:type_name -> odc.Property + 6, // 10: odc.ConfigureRequest.request:type_name -> odc.StateRequest + 6, // 11: odc.StartRequest.request:type_name -> odc.StateRequest + 6, // 12: odc.StopRequest.request:type_name -> odc.StateRequest + 6, // 13: odc.ResetRequest.request:type_name -> odc.StateRequest + 6, // 14: odc.TerminateRequest.request:type_name -> odc.StateRequest + 10, // 15: odc.ODC.Initialize:input_type -> odc.InitializeRequest + 11, // 16: odc.ODC.Submit:input_type -> odc.SubmitRequest + 12, // 17: odc.ODC.Activate:input_type -> odc.ActivateRequest + 13, // 18: odc.ODC.Run:input_type -> odc.RunRequest + 14, // 19: odc.ODC.Update:input_type -> odc.UpdateRequest + 18, // 20: odc.ODC.Configure:input_type -> odc.ConfigureRequest + 17, // 21: odc.ODC.SetProperties:input_type -> odc.SetPropertiesRequest + 6, // 22: odc.ODC.GetState:input_type -> odc.StateRequest + 19, // 23: odc.ODC.Start:input_type -> odc.StartRequest + 20, // 24: odc.ODC.Stop:input_type -> odc.StopRequest + 21, // 25: odc.ODC.Reset:input_type -> odc.ResetRequest + 22, // 26: odc.ODC.Terminate:input_type -> odc.TerminateRequest + 15, // 27: odc.ODC.Shutdown:input_type -> odc.ShutdownRequest + 23, // 28: odc.ODC.Status:input_type -> odc.StatusRequest + 3, // 29: odc.ODC.Initialize:output_type -> odc.GeneralReply + 3, // 30: odc.ODC.Submit:output_type -> odc.GeneralReply + 3, // 31: odc.ODC.Activate:output_type -> odc.GeneralReply + 3, // 32: odc.ODC.Run:output_type -> odc.GeneralReply + 3, // 33: odc.ODC.Update:output_type -> odc.GeneralReply + 7, // 34: odc.ODC.Configure:output_type -> odc.StateReply + 3, // 35: odc.ODC.SetProperties:output_type -> odc.GeneralReply + 7, // 36: odc.ODC.GetState:output_type -> odc.StateReply + 7, // 37: odc.ODC.Start:output_type -> odc.StateReply + 7, // 38: odc.ODC.Stop:output_type -> odc.StateReply + 7, // 39: odc.ODC.Reset:output_type -> odc.StateReply + 7, // 40: odc.ODC.Terminate:output_type -> odc.StateReply + 3, // 41: odc.ODC.Shutdown:output_type -> odc.GeneralReply + 9, // 42: odc.ODC.Status:output_type -> odc.StatusReply + 29, // [29:43] is the sub-list for method output_type + 15, // [15:29] is the sub-list for method input_type + 15, // [15:15] is the sub-list for extension type_name + 15, // [15:15] is the sub-list for extension extendee + 0, // [0:15] is the sub-list for field type_name } func init() { file_protos_odc_proto_init() } @@ -1998,7 +2089,7 @@ func file_protos_odc_proto_init() { } } file_protos_odc_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StateRequest); i { + switch v := v.(*Collection); i { case 0: return &v.state case 1: @@ -2010,7 +2101,7 @@ func file_protos_odc_proto_init() { } } file_protos_odc_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StateReply); i { + switch v := v.(*StateRequest); i { case 0: return &v.state case 1: @@ -2022,7 +2113,7 @@ func file_protos_odc_proto_init() { } } file_protos_odc_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PartitionStatus); i { + switch v := v.(*StateReply); i { case 0: return &v.state case 1: @@ -2034,7 +2125,7 @@ func file_protos_odc_proto_init() { } } file_protos_odc_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StatusReply); i { + switch v := v.(*PartitionStatus); i { case 0: return &v.state case 1: @@ -2046,7 +2137,7 @@ func file_protos_odc_proto_init() { } } file_protos_odc_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InitializeRequest); i { + switch v := v.(*StatusReply); i { case 0: return &v.state case 1: @@ -2058,7 +2149,7 @@ func file_protos_odc_proto_init() { } } file_protos_odc_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SubmitRequest); i { + switch v := v.(*InitializeRequest); i { case 0: return &v.state case 1: @@ -2070,7 +2161,7 @@ func file_protos_odc_proto_init() { } } file_protos_odc_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ActivateRequest); i { + switch v := v.(*SubmitRequest); i { case 0: return &v.state case 1: @@ -2082,7 +2173,7 @@ func file_protos_odc_proto_init() { } } file_protos_odc_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RunRequest); i { + switch v := v.(*ActivateRequest); i { case 0: return &v.state case 1: @@ -2094,7 +2185,7 @@ func file_protos_odc_proto_init() { } } file_protos_odc_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpdateRequest); i { + switch v := v.(*RunRequest); i { case 0: return &v.state case 1: @@ -2106,7 +2197,7 @@ func file_protos_odc_proto_init() { } } file_protos_odc_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ShutdownRequest); i { + switch v := v.(*UpdateRequest); i { case 0: return &v.state case 1: @@ -2118,7 +2209,7 @@ func file_protos_odc_proto_init() { } } file_protos_odc_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Property); i { + switch v := v.(*ShutdownRequest); i { case 0: return &v.state case 1: @@ -2130,7 +2221,7 @@ func file_protos_odc_proto_init() { } } file_protos_odc_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetPropertiesRequest); i { + switch v := v.(*Property); i { case 0: return &v.state case 1: @@ -2142,7 +2233,7 @@ func file_protos_odc_proto_init() { } } file_protos_odc_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ConfigureRequest); i { + switch v := v.(*SetPropertiesRequest); i { case 0: return &v.state case 1: @@ -2154,7 +2245,7 @@ func file_protos_odc_proto_init() { } } file_protos_odc_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StartRequest); i { + switch v := v.(*ConfigureRequest); i { case 0: return &v.state case 1: @@ -2166,7 +2257,7 @@ func file_protos_odc_proto_init() { } } file_protos_odc_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StopRequest); i { + switch v := v.(*StartRequest); i { case 0: return &v.state case 1: @@ -2178,7 +2269,7 @@ func file_protos_odc_proto_init() { } } file_protos_odc_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ResetRequest); i { + switch v := v.(*StopRequest); i { case 0: return &v.state case 1: @@ -2190,7 +2281,7 @@ func file_protos_odc_proto_init() { } } file_protos_odc_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TerminateRequest); i { + switch v := v.(*ResetRequest); i { case 0: return &v.state case 1: @@ -2202,6 +2293,18 @@ func file_protos_odc_proto_init() { } } file_protos_odc_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TerminateRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_protos_odc_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*StatusRequest); i { case 0: return &v.state @@ -2220,7 +2323,7 @@ func file_protos_odc_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_protos_odc_proto_rawDesc, NumEnums: 2, - NumMessages: 21, + NumMessages: 22, NumExtensions: 0, NumServices: 1, }, diff --git a/core/integration/odc/protos/odc.proto b/core/integration/odc/protos/odc.proto index 9ce3c187b..6caa07a76 100644 --- a/core/integration/odc/protos/odc.proto +++ b/core/integration/odc/protos/odc.proto @@ -58,8 +58,8 @@ enum SessionStatus { message Error { string msg = 1; // Detailed error message int32 code = 2; // Error code. - // TODO: Make error codes specific for each concrete request and/or error type. - // TODO: Add link to a documented error codes. + // TODO: Make error codes specific for each concrete request and/or error type. + // TODO: Add link to a documented error codes. } // General reply to requests @@ -89,6 +89,14 @@ message Device { string rmsjobid = 7; // job IDs from the resource management system } +//Collection information +message Collection { + uint64 id = 1; // Runtime collection ID (same as in DDS) + string state = 2; // Aggregated state as string + string path = 3; // Path in the topology + string host = 5; // Host where the collection runs +} + // Device change/get state request message StateRequest { string partitionid = 1; // Partition ID from ECS @@ -102,6 +110,7 @@ message StateRequest { message StateReply { GeneralReply reply = 1; // General reply. See GeneralReply message for details. repeated Device devices = 2; // If detailed reply is requested then this field contains a list of affected devices otherwise it's empty. + repeated Collection collections = 3; // If detailed reply is requested then this field contains a list of affected collections otherwise it's empty. } // Status of each partition From ddc3b5bf9e9565e1f62a22a8c7aee74ff909cf66 Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Fri, 30 May 2025 09:38:57 +0200 Subject: [PATCH 02/25] [core] expose ODC collection info in the plugin GetEnvironmentsData --- core/integration/odc/plugin.go | 86 ++++++++++++++++++++++++++++++---- 1 file changed, 78 insertions(+), 8 deletions(-) diff --git a/core/integration/odc/plugin.go b/core/integration/odc/plugin.go index 11a1d9fa3..a282dbddf 100644 --- a/core/integration/odc/plugin.go +++ b/core/integration/odc/plugin.go @@ -95,20 +95,22 @@ type OdcStatus struct { } type OdcDeviceId uint64 +type OdcCollectionId uint64 func (o OdcDeviceId) MarshalJSON() ([]byte, error) { return json.Marshal(strconv.FormatUint(uint64(o), 10)) } type OdcPartitionInfo struct { - PartitionId uid.ID `json:"-"` - RunNumber uint32 `json:"runNumber"` - State string `json:"state"` - EcsState sm.State `json:"ecsState"` - DdsSessionId string `json:"ddsSessionId"` - DdsSessionStatus string `json:"ddsSessionStatus"` - Devices map[OdcDeviceId]*OdcDevice `json:"devices"` - Hosts []string `json:"hosts"` + PartitionId uid.ID `json:"-"` + RunNumber uint32 `json:"runNumber"` + State string `json:"state"` + EcsState sm.State `json:"ecsState"` + DdsSessionId string `json:"ddsSessionId"` + DdsSessionStatus string `json:"ddsSessionStatus"` + Devices map[OdcDeviceId]*OdcDevice `json:"devices"` + Hosts []string `json:"hosts"` + Collections map[OdcCollectionId]*OdcCollection `json:"collections"` } type OdcDevice struct { @@ -122,6 +124,14 @@ type OdcDevice struct { Rmsjobid string `json:"rmsjobid"` } +type OdcCollection struct { + CollectionId OdcCollectionId `json:"collectionId"` + State string `json:"state"` + EcsState sm.State `json:"ecsState"` + Path string `json:"path"` + Host string `json:"host"` +} + type partitionStateChangedEventPayload struct { PartitionId uid.ID `json:"partitionId"` DdsSessionId string `json:"ddsSessionId"` @@ -144,6 +154,17 @@ type deviceStateChangedEventPayload struct { Rmsjobid string `json:"rmsjobid"` } +type collectionStateChangedEventPayload struct { + PartitionId uid.ID `json:"partitionId"` + DdsSessionId string `json:"ddsSessionId"` + DdsSessionStatus string `json:"ddsSessionStatus"` + State string `json:"state"` + EcsState sm.State `json:"ecsState"` + CollectionId OdcCollectionId `json:"collectionId"` + Path string `json:"path"` + Host string `json:"host"` +} + func NewPlugin(endpoint string) integration.Plugin { u, err := url.Parse(endpoint) if err != nil { @@ -273,6 +294,16 @@ func (p *Plugin) queryPartitionStatus() { Rmsjobid: device.Rmsjobid, } } + odcPartInfoSlice[idx].Collections = make(map[OdcCollectionId]*OdcCollection, len(odcPartStateRep.Collections)) + for _, collection := range odcPartStateRep.Collections { + odcPartInfoSlice[idx].Collections[OdcCollectionId(collection.Id)] = &OdcCollection{ + CollectionId: OdcCollectionId(collection.Id), + State: collection.State, + EcsState: fairmq.ToEcsState(collection.State, sm.UNKNOWN), + Path: collection.Path, + Host: collection.Host, + } + } }(i, id) } wg.Wait() @@ -337,6 +368,45 @@ func (p *Plugin) queryPartitionStatus() { }) } + // detection of collection state change + event publication + for collectionId, collection := range partitionInfo.Collections { + existingCollection, hasCollection := existingPartition.Collections[collectionId] + + oldEcsState := sm.UNKNOWN // we presume the collection didn't exist before + + // if a collection with this ID is already known to us from before + if hasCollection { + // if collection state has changed + if existingCollection.State != collection.State { + // if the state has changed, we take note of the previous state + oldEcsState = existingCollection.EcsState + } else { + // if the state hasn't changed, we set the old ECS state and bail + collection.EcsState = existingCollection.EcsState + continue + } + } + + collection.EcsState = fairmq.ToEcsState(collection.State, oldEcsState) + + payload := collectionStateChangedEventPayload{ + PartitionId: partitionInfo.PartitionId, + DdsSessionId: partitionInfo.DdsSessionId, + DdsSessionStatus: partitionInfo.DdsSessionStatus, + State: collection.State, + EcsState: collection.EcsState, + CollectionId: collection.CollectionId, + Path: collection.Path, + Host: collection.Host, + } + payloadJson, _ := json.Marshal(payload) + the.EventWriterWithTopic(TOPIC).WriteEvent(&pb.Ev_IntegratedServiceEvent{ + Name: "odc.collectionStateChanged", + EnvironmentId: id.String(), + Payload: string(payloadJson[:]), + }) + } + // detection of env (ODC partition) state change + event publication if existingPartition.State != partitionInfo.State { partitionInfo.EcsState = fairmq.ToEcsState(partitionInfo.State, existingPartition.EcsState) From f67074cd3334eee76b0eafe98eb1a57ae60a2ea8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Tich=C3=A1k?= Date: Tue, 21 Oct 2025 17:56:30 +0200 Subject: [PATCH 03/25] [OCTRL-1052] Provide description how to run readout with CRU from ECS --- docs/running_docker.md | 74 +++++++++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 30 deletions(-) diff --git a/docs/running_docker.md b/docs/running_docker.md index e5d43698a..11fbb4fbd 100644 --- a/docs/running_docker.md +++ b/docs/running_docker.md @@ -4,7 +4,7 @@ > This method is **not intended for production use**. > It serves only as a **proof of concept** for testing Docker images as part of an existing pipeline. > -> Currently, it has been tested with the `alma9-flp-node` image running the *readout* component. +> Currently, it was tested with the `alma9-flp-node` image running the *readout* component with CRU. --- @@ -45,55 +45,69 @@ For example, to run readout, modify the `_plain_command` section of [`readout.ya When running readout, we successfully used the following command inside the `alma9-flp-node` image: ```bash -sudo /usr/bin/docker run --name readout --replace \ - --user "$(id -u flp):$(id -u flp)" \ +sudo -E docker run --name readout --replace \ + --user flp -v /etc/group:/etc/group:ro -v /etc/passwd:/etc/passwd:ro \ + --privileged \ --network=host --ipc=host \ - -e O2_DETECTOR -e O2_PARTITION -e OCC_CONTROL_PORT \ - -e O2_SYSTEM -e O2_ROLE \ + -v /tmp:/tmp \ + -v /lib/modules/$(uname -r):/lib/modules/$(uname -r) \ + -e O2_DETECTOR -e O2_PARTITION -e OCC_CONTROL_PORT -e O2_SYSTEM -e O2_ROLE \ gitlab-registry.cern.ch/aliceo2group/dockerfiles/alma9-flp-node:2 \ /opt/o2/bin/o2-readout-exe ``` > 🧩 **Note** > We are not claiming that this is the most efficient way how to run this image, just that it works. +> +#### Explanation of command + +Let's explain all parts of the `docker run` command and what is their purpose. As RHEL uses Podman by default +instead of docker we are going to comment on Podman parameters, but docker should be equivalent or pretty close. + +- `sudo -E` switch to the rootful mode of Podman and pass all of the environment variables +- `docker run --name readout --replace` start container with the name readout and replace already existing container +- `--privileged` runs container with extended privileges and allows access to the devices and other resources +on host system with the same privileges as user running the container (`flp` in our case). Readout communicates +directly with CRUs and others connected via PCIe so we need to make these available inside the container. +- `--user flp -v /etc/group:/etc/group:ro -v /etc/passwd:/etc/passwd:ro` run container as flp user provide same user +and group settings as on a host machine. This is necessary as readout is using shared memory which is mapped under +flp user and needs access to [BAR](https://github.com/AliceO2Group/ReadoutCard?tab=readme-ov-file#bar-interface) +interfaces of CRU which belong to the `pda` group. We used this way of setting up user privileges and ids as there is +no guarantee that ids would match if we would hardwire user into docker image +- `--network=host` bind container's network to the host's. This allows services running outside of docker to communicate +with internals (eg. gRPC, IL, ... ). It should be changed to open just required ports. +- `--ipc=host` readout uses FairMQ which communicates through shared memory Inter-Process Communication. +As we are now running readout inside the docker with the rest of data distribution running bare metal we +need to have access to the hosting OS shared memory. This is the main requirement for running as rootful. +If we run container in rootless mode with this flag set, Podman switches into elevated privileges mode that blocks +other cli commands from the same user command until this command is finished unless running under root. +We tried to just bind `/dev/shm/` but readout failed on permission errors. +- `-v /tmp:/tmp` binds `/tmp` of host to the container for monitoring purposes. +- `-v /lib/modules/$(uname -r):/lib/modules/$(uname -r)` binds folder with host's kernel modules for the usage of PDA +used by readout itself. +- `e ...` pass environment variables required by readout to the container #### Environment Variables -To identify all required environment variables: +--- + +## Tips and Tricks + +- To identify all required environment variables: 1. Open the **ECS GUI**. 2. Go to the **Environment Details** page for the relevant task. 3. Review the variables defined there — these match those used when running the binary outside Docker. -#### Shared Memory Communication - -To enable shared memory communication between processes, add the `--ipc=host` flag when running the container. -However, doing so requires **elevated privileges**. - -While **Podman** can run without root privileges, it pauses other Podman processes for the same user. -This means commands like `podman ps -a` or starting multiple containers in parallel will not work. - -Therefore, you should run containers using the same user as the rest of the pipeline: - -```bash ---user "$(id -u flp):$(id -u flp)" -``` - -This ensures shared memory segments are created under the same user context. - ---- - -## Tips and Tricks - -* Production systems running RHEL do not install native Docker via: +- Production systems running RHEL do not install native Docker via: ```bash dnf install docker ``` - Instead, they use **Podman**, which emulates Docker’s behavior but may differ in certain aspects. + Instead, they use Podman, which emulates Docker’s behavior but may differ in certain aspects. -* To check whether ECS has started a container, run: +- To check whether ECS has started a container, run: ```bash docker ps -a @@ -107,7 +121,7 @@ This ensures shared memory segments are created under the same user context. > su - flp > ``` -* To view container logs directly from Docker: +- To view container logs directly from Docker: ```bash docker logs From 94c397fe4833f80eef6c301f88630720374e19d4 Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Fri, 24 Oct 2025 09:00:06 +0200 Subject: [PATCH 04/25] use a group name for the kafka reader otherwise, we will not get all messages among multiple partitions/replicas. --- core/integration/lhc/plugin.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/integration/lhc/plugin.go b/core/integration/lhc/plugin.go index bb4276551..1d5853d91 100644 --- a/core/integration/lhc/plugin.go +++ b/core/integration/lhc/plugin.go @@ -70,7 +70,7 @@ func (p *Plugin) Init(_ string) error { // use a background context for reader loop; Destroy will Close the reader p.ctx = context.Background() - p.reader = cmnevent.NewReaderWithTopic(dipClientTopic, "", true) + p.reader = cmnevent.NewReaderWithTopic(dipClientTopic, "o2-aliecs-core.lhc", true) if p.reader == nil { return errors.New("could not create a kafka reader for LHC plugin") From c64a5947f022bd17016d4bbbbfffbc6eecb55e53 Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Wed, 29 Oct 2025 09:00:21 +0100 Subject: [PATCH 05/25] Rework handling failed GO_ERROR In this commit we unify the way that a failed GO_ERROR is handled. We recognize invalid event errors as harmless (ERROR->ERROR is pointless, DONE->ERROR is too late). Any other case is very much unexpected and we print a visible error and comply with the previous behaviour - setting EROR state manually. Closes OCTRL-1064. --- core/environment/environment.go | 18 ++---------- core/environment/manager.go | 28 ++++-------------- core/environment/utils.go | 26 +++++++++++++++++ core/environment/utils_test.go | 50 +++++++++++++++++++++++++++++++++ 4 files changed, 83 insertions(+), 39 deletions(-) create mode 100644 core/environment/utils_test.go diff --git a/core/environment/environment.go b/core/environment/environment.go index 34241d782..f75367461 100644 --- a/core/environment/environment.go +++ b/core/environment/environment.go @@ -1232,19 +1232,8 @@ func (env *Environment) subscribeToWfState(taskman *task.Manager) { NewEnvGoErrorEvent(env, newCriticalTasksErrorMessage(env)), ) err := env.TryTransition(NewGoErrorTransition(taskman)) - if err != nil { - if env.Sm.Current() == "ERROR" { - log.WithField("partition", env.id). - WithField("level", infologger.IL_Devel). - Info("skipped requested transition to ERROR: environment already in ERROR state") - } else { - log.WithField("partition", env.id). - WithError(err). - WithField("level", infologger.IL_Devel). - Warn("could not transition gently to ERROR, forcing it") - env.setState(wfState.String()) - } + handleFailedGoError(err, env) } }) break WORKFLOW_STATE_LOOP @@ -1472,10 +1461,7 @@ func (env *Environment) scheduleAutoStopTransition() (scheduled bool, expected t err = env.TryTransition(NewGoErrorTransition(ManagerInstance().taskman)) if err != nil { - log.WithField("partition", env.id). - WithField("run", env.currentRunNumber). - Errorf("Forced transition to ERROR failed: %s", err.Error()) - env.setState("ERROR") + handleFailedGoError(err, env) } return } diff --git a/core/environment/manager.go b/core/environment/manager.go index e797f257a..5c732607e 100644 --- a/core/environment/manager.go +++ b/core/environment/manager.go @@ -496,10 +496,7 @@ func (envs *Manager) CreateEnvironment(workflowPath string, userVars map[string] envs.taskman), ) if err != nil { - log.WithField("partition", env.Id().String()). - WithField("state", envState). - Debug("could not transition failed auto-transitioning environment to ERROR, cleanup in progress") - env.setState("ERROR") + handleFailedGoError(err, env) } envTasks := env.Workflow().GetTasks() @@ -603,10 +600,7 @@ func (envs *Manager) CreateEnvironment(workflowPath string, userVars map[string] envs.taskman), ) if errTxErr != nil { - log.WithField("partition", env.Id().String()). - WithField("state", envState). - WithError(errTxErr). - Debug("could not transition to ERROR after failed deployment/configuration, cleanup in progress") + handleFailedGoError(errTxErr, env) } envTasks := env.Workflow().GetTasks() // TeardownEnvironment manages the envs.mu internally @@ -1064,11 +1058,7 @@ func (envs *Manager) handleIntegratedServiceEvent(evt event.IntegratedServiceEve ) err = env.TryTransition(NewGoErrorTransition(envs.taskman)) if err != nil { - log.WithPrefix("scheduler"). - WithField("partition", envId.String()). - WithError(err). - Error("environment GO_ERROR transition failed after ODC_PARTITION_STATE_CHANGE ERROR event") - env.setState("ERROR") + handleFailedGoError(err, env) } } }() @@ -1124,12 +1114,7 @@ func (envs *Manager) handleLhcEvents(evt event.IntegratedServiceEvent) { if env.CurrentState() != "ERROR" { err = env.TryTransition(NewGoErrorTransition(envs.taskman)) if err != nil { - log.WithPrefix("scheduler"). - WithField("partition", envId.String()). - WithField("run", env.currentRunNumber). - WithError(err). - Error("environment GO_ERROR transition failed after a beam dump event, forcing") - env.setState("ERROR") + handleFailedGoError(err, env) } } } @@ -1483,11 +1468,8 @@ func (envs *Manager) CreateAutoEnvironment(workflowPath string, userVars map[str envs.taskman), ) if err != nil { - log.WithField("partition", env.Id().String()). - WithField("state", envState). - Debug("could not transition failed auto-transitioning environment to ERROR, cleanup in progress") + handleFailedGoError(err, env) env.sendEnvironmentEvent(&event.EnvironmentEvent{Message: "transition ERROR failed, forcing", EnvironmentID: env.Id().String(), Error: err}) - env.setState("ERROR") } envTasks := env.Workflow().GetTasks() diff --git a/core/environment/utils.go b/core/environment/utils.go index 229fde3e1..b5367d248 100644 --- a/core/environment/utils.go +++ b/core/environment/utils.go @@ -27,12 +27,14 @@ package environment import ( "bytes" "encoding/json" + "errors" "fmt" "github.com/AliceO2Group/Control/common/logger/infologger" pb "github.com/AliceO2Group/Control/common/protos" "github.com/AliceO2Group/Control/core/task" "github.com/AliceO2Group/Control/core/task/sm" "github.com/AliceO2Group/Control/core/workflow" + "github.com/looplab/fsm" "os" "sort" @@ -139,3 +141,27 @@ func newCriticalTasksErrorMessage(env *Environment) string { return fmt.Sprintf("%d critical tasks transitioned to ERROR, could not determine the first one to fail", len(criticalTasksInError)) } } + +func handleFailedGoError(err error, env *Environment) { + var invalidEventErr *fsm.InvalidEventError + if errors.As(err, &invalidEventErr) { + // this case can occur if the environment is in either: + // - ERROR (env already transitioned to ERROR for another reason) + // - DONE (an error might have occurred during teardown, but it's already over, no point in spreading panic) + log.WithError(invalidEventErr). + WithField("partition", env.Id().String()). + WithField("run", env.currentRunNumber). + WithField("state", env.CurrentState()). + WithField(infologger.Level, infologger.IL_Support). + Warn("did not perform GO_ERROR transition") + } else { + // in principle this should never happen, so we log it accordingly and force the ERROR state just in case + log.WithError(err). + WithField("partition", env.Id().String()). + WithField("run", env.currentRunNumber). + WithField("state", env.CurrentState()). + WithField(infologger.Level, infologger.IL_Ops). + Error("could not perform GO_ERROR transition due to unexpected error, forcing...") + env.setState("ERROR") + } +} diff --git a/core/environment/utils_test.go b/core/environment/utils_test.go new file mode 100644 index 000000000..24e205d30 --- /dev/null +++ b/core/environment/utils_test.go @@ -0,0 +1,50 @@ +/* + * === This file is part of ALICE O² === + * + * Copyright 2025 CERN and copyright holders of ALICE O². + * Author: Piotr Konopka + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In applying this license CERN does not waive the privileges and + * immunities granted to it by virtue of its status as an + * Intergovernmental Organization or submit itself to any jurisdiction. + */ + +package environment + +import ( + "github.com/looplab/fsm" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +var _ = Describe("handleFailedGoError", func() { + It("does not overwrite state for InvalidEventError", func() { + env := &Environment{} + env.Sm = fsm.NewFSM("DONE", fsm.Events{}, fsm.Callbacks{}) + Expect(env.Sm.Current()).To(Equal("DONE")) + + handleFailedGoError(&fsm.InvalidEventError{Event: "GO_ERROR", State: "DONE"}, env) + Expect(env.Sm.Current()).To(Equal("DONE")) + }) + + It("overwrites state to ERROR for other errors", func() { + env := &Environment{} + env.Sm = fsm.NewFSM("CONFIGURED", fsm.Events{}, fsm.Callbacks{}) + + handleFailedGoError(fsm.UnknownEventError{Event: "BOOM"}, env) + Expect(env.Sm.Current()).To(Equal("ERROR")) + }) +}) From e3283bd7694dd6ee7504e759ed39235a5ec488f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Tich=C3=A1k?= Date: Thu, 30 Oct 2025 14:13:09 +0100 Subject: [PATCH 06/25] [odc] OCTRL-1015: fill in EcsState properly --- core/integration/odc/plugin.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/integration/odc/plugin.go b/core/integration/odc/plugin.go index a282dbddf..9311aa177 100644 --- a/core/integration/odc/plugin.go +++ b/core/integration/odc/plugin.go @@ -251,6 +251,7 @@ func (p *Plugin) queryPartitionStatus() { PartitionId: id, RunNumber: uint32(odcPartSt.Runnr), State: odcPartSt.State, + EcsState: fairmq.ToEcsState(odcPartSt.State, sm.UNKNOWN), DdsSessionId: odcPartSt.Sessionid, DdsSessionStatus: odcPartSt.Status.String(), } @@ -287,6 +288,7 @@ func (p *Plugin) queryPartitionStatus() { odcPartInfoSlice[idx].Devices[OdcDeviceId(device.Id)] = &OdcDevice{ TaskId: strconv.FormatUint(device.Id, 10), State: device.State, + EcsState: fairmq.ToEcsState(device.State, sm.UNKNOWN), Path: device.Path, Ignored: device.Ignored, Host: device.Host, From a3fd1f2538b0f8474d234cec5e2c199ab6d2acd5 Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Fri, 31 Oct 2025 10:01:26 +0100 Subject: [PATCH 07/25] fix recognizing InvalidEventError in handleFailedGoError Fixing an issue caused by the fact that I have no idea what I'm doing in Go. fsm.InvalidEventError implements Error() with a value receiver, which actually allows to provide an error as a value or as a pointer. However, errors.As() is not smart about it and does not strip the type from references/pointers/etc, so the original version would work only with errors passed as pointers. This commit modifies the helper to work correctly with errors provided as values, which is the more natural way to use it. Unfortunately it is not possible to prevent a caller from passing an error pointer. Let's consider it as a part of OCTRL-1064. --- core/environment/utils.go | 7 ++++--- core/environment/utils_test.go | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/core/environment/utils.go b/core/environment/utils.go index b5367d248..f05c0e3cb 100644 --- a/core/environment/utils.go +++ b/core/environment/utils.go @@ -29,14 +29,15 @@ import ( "encoding/json" "errors" "fmt" + "os" + "sort" + "github.com/AliceO2Group/Control/common/logger/infologger" pb "github.com/AliceO2Group/Control/common/protos" "github.com/AliceO2Group/Control/core/task" "github.com/AliceO2Group/Control/core/task/sm" "github.com/AliceO2Group/Control/core/workflow" "github.com/looplab/fsm" - "os" - "sort" "github.com/AliceO2Group/Control/core/the" "gopkg.in/yaml.v3" @@ -143,7 +144,7 @@ func newCriticalTasksErrorMessage(env *Environment) string { } func handleFailedGoError(err error, env *Environment) { - var invalidEventErr *fsm.InvalidEventError + var invalidEventErr fsm.InvalidEventError if errors.As(err, &invalidEventErr) { // this case can occur if the environment is in either: // - ERROR (env already transitioned to ERROR for another reason) diff --git a/core/environment/utils_test.go b/core/environment/utils_test.go index 24e205d30..035f361a3 100644 --- a/core/environment/utils_test.go +++ b/core/environment/utils_test.go @@ -36,7 +36,7 @@ var _ = Describe("handleFailedGoError", func() { env.Sm = fsm.NewFSM("DONE", fsm.Events{}, fsm.Callbacks{}) Expect(env.Sm.Current()).To(Equal("DONE")) - handleFailedGoError(&fsm.InvalidEventError{Event: "GO_ERROR", State: "DONE"}, env) + handleFailedGoError(fsm.InvalidEventError{Event: "GO_ERROR", State: "DONE"}, env) Expect(env.Sm.Current()).To(Equal("DONE")) }) From 5c463fa0ee650eb2e233c429d5f58d8b0aeba718 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Tich=C3=A1k?= Date: Fri, 31 Oct 2025 11:50:06 +0100 Subject: [PATCH 08/25] [doc] add link for EPN workflow generation --- README.md | 1 + docs/handbook/configuration.md | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/README.md b/README.md index 18b4c98f9..4889d30cb 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,7 @@ There are two ways of interacting with AliECS: * [Task template structure](/docs/handbook/configuration.md#task-template-structure) * [Variables pushed to controlled tasks](/docs/handbook/configuration.md#variables-pushed-to-controlled-tasks) * [Resource wants and limits](/docs/handbook/configuration.md#resource-wants-and-limits) + * [EPN workflow generation](/docs/handbook/configuration.md#epn-workflow-generation) * [Integration plugins](/core/integration/README.md#integration-plugins) * [Plugin system overview](/core/integration/README.md#plugin-system-overview) * [Integrated service operations](/core/integration/README.md#integrated-service-operations) diff --git a/docs/handbook/configuration.md b/docs/handbook/configuration.md index 798114606..637fb59a5 100644 --- a/docs/handbook/configuration.md +++ b/docs/handbook/configuration.md @@ -469,3 +469,9 @@ limits: defaults: (...) ``` + +## EPN workflow generation + +Workflow generation for EPNs is not the responsibility of ECS, but you can find +more details [here](https://alice-pdp-operations.docs.cern.ch/workflow/#for-the-epns). + From ae22899ee61d312a50670f9ac87c69f68b3e136a Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Thu, 30 Oct 2025 15:18:17 +0100 Subject: [PATCH 09/25] Perform GO_ERROR after failed STOP_ACTIVITY and RESET during env destruction Even if we destroy an environment, it is good to recognize that it was not a healthy shutdown, e.g. for bookkeeping reasons. Also, we might miss out on some necessary calls to integrated services by not going to ERROR. Fixes OCTRL-1063. --- core/environment/environment.go | 4 ++-- core/environment/manager.go | 10 +++++----- core/environment/utils.go | 2 +- core/environment/utils_test.go | 6 +++--- core/server.go | 28 ++++++++++++++++++++++------ 5 files changed, 33 insertions(+), 17 deletions(-) diff --git a/core/environment/environment.go b/core/environment/environment.go index f75367461..e42620093 100644 --- a/core/environment/environment.go +++ b/core/environment/environment.go @@ -1233,7 +1233,7 @@ func (env *Environment) subscribeToWfState(taskman *task.Manager) { ) err := env.TryTransition(NewGoErrorTransition(taskman)) if err != nil { - handleFailedGoError(err, env) + HandleFailedGoError(err, env) } }) break WORKFLOW_STATE_LOOP @@ -1461,7 +1461,7 @@ func (env *Environment) scheduleAutoStopTransition() (scheduled bool, expected t err = env.TryTransition(NewGoErrorTransition(ManagerInstance().taskman)) if err != nil { - handleFailedGoError(err, env) + HandleFailedGoError(err, env) } return } diff --git a/core/environment/manager.go b/core/environment/manager.go index 5c732607e..c494e90fe 100644 --- a/core/environment/manager.go +++ b/core/environment/manager.go @@ -496,7 +496,7 @@ func (envs *Manager) CreateEnvironment(workflowPath string, userVars map[string] envs.taskman), ) if err != nil { - handleFailedGoError(err, env) + HandleFailedGoError(err, env) } envTasks := env.Workflow().GetTasks() @@ -600,7 +600,7 @@ func (envs *Manager) CreateEnvironment(workflowPath string, userVars map[string] envs.taskman), ) if errTxErr != nil { - handleFailedGoError(errTxErr, env) + HandleFailedGoError(errTxErr, env) } envTasks := env.Workflow().GetTasks() // TeardownEnvironment manages the envs.mu internally @@ -1058,7 +1058,7 @@ func (envs *Manager) handleIntegratedServiceEvent(evt event.IntegratedServiceEve ) err = env.TryTransition(NewGoErrorTransition(envs.taskman)) if err != nil { - handleFailedGoError(err, env) + HandleFailedGoError(err, env) } } }() @@ -1114,7 +1114,7 @@ func (envs *Manager) handleLhcEvents(evt event.IntegratedServiceEvent) { if env.CurrentState() != "ERROR" { err = env.TryTransition(NewGoErrorTransition(envs.taskman)) if err != nil { - handleFailedGoError(err, env) + HandleFailedGoError(err, env) } } } @@ -1468,7 +1468,7 @@ func (envs *Manager) CreateAutoEnvironment(workflowPath string, userVars map[str envs.taskman), ) if err != nil { - handleFailedGoError(err, env) + HandleFailedGoError(err, env) env.sendEnvironmentEvent(&event.EnvironmentEvent{Message: "transition ERROR failed, forcing", EnvironmentID: env.Id().String(), Error: err}) } diff --git a/core/environment/utils.go b/core/environment/utils.go index f05c0e3cb..1ca0dcad3 100644 --- a/core/environment/utils.go +++ b/core/environment/utils.go @@ -143,7 +143,7 @@ func newCriticalTasksErrorMessage(env *Environment) string { } } -func handleFailedGoError(err error, env *Environment) { +func HandleFailedGoError(err error, env *Environment) { var invalidEventErr fsm.InvalidEventError if errors.As(err, &invalidEventErr) { // this case can occur if the environment is in either: diff --git a/core/environment/utils_test.go b/core/environment/utils_test.go index 035f361a3..bf914be83 100644 --- a/core/environment/utils_test.go +++ b/core/environment/utils_test.go @@ -30,13 +30,13 @@ import ( . "github.com/onsi/gomega" ) -var _ = Describe("handleFailedGoError", func() { +var _ = Describe("HandleFailedGoError", func() { It("does not overwrite state for InvalidEventError", func() { env := &Environment{} env.Sm = fsm.NewFSM("DONE", fsm.Events{}, fsm.Callbacks{}) Expect(env.Sm.Current()).To(Equal("DONE")) - handleFailedGoError(fsm.InvalidEventError{Event: "GO_ERROR", State: "DONE"}, env) + HandleFailedGoError(fsm.InvalidEventError{Event: "GO_ERROR", State: "DONE"}, env) Expect(env.Sm.Current()).To(Equal("DONE")) }) @@ -44,7 +44,7 @@ var _ = Describe("handleFailedGoError", func() { env := &Environment{} env.Sm = fsm.NewFSM("CONFIGURED", fsm.Events{}, fsm.Callbacks{}) - handleFailedGoError(fsm.UnknownEventError{Event: "BOOM"}, env) + HandleFailedGoError(fsm.UnknownEventError{Event: "BOOM"}, env) Expect(env.Sm.Current()).To(Equal("ERROR")) }) }) diff --git a/core/server.go b/core/server.go index 86bacb288..b6e50b816 100644 --- a/core/server.go +++ b/core/server.go @@ -718,10 +718,18 @@ func (m *RpcServer) DestroyEnvironment(cxt context.Context, req *pb.DestroyEnvir } if req.AllowInRunningState && env.CurrentState() == "RUNNING" { - err = env.TryTransition(environment.MakeTransition(m.state.taskman, pb.ControlEnvironmentRequest_STOP_ACTIVITY)) + err = env.TryTransition(environment.NewStopActivityTransition(m.state.taskman)) if err != nil { - log.WithField("partition", env.Id().String()). - Warn("could not perform STOP transition for environment teardown, forcing") + log.WithError(err). + WithField("partition", env.Id().String()). + Warn("could not perform STOP transition for environment teardown, going to ERROR, then forcing") + the.EventWriterWithTopic(topic.Environment).WriteEvent( + environment.NewEnvGoErrorEvent(env, "STOP_ACTIVITY during environment destruction failed"), + ) + err = env.TryTransition(environment.NewGoErrorTransition(m.state.taskman)) + if err != nil { + environment.HandleFailedGoError(err, env) + } reply, err = m.doTeardownAndCleanup(env, true /*force*/, false /*keepTasks*/) return } @@ -746,10 +754,18 @@ func (m *RpcServer) DestroyEnvironment(cxt context.Context, req *pb.DestroyEnvir // This might transition to STANDBY if needed, or do nothing if we're already there if env.CurrentState() == "CONFIGURED" { - err = env.TryTransition(environment.MakeTransition(m.state.taskman, pb.ControlEnvironmentRequest_RESET)) + err = env.TryTransition(environment.NewResetTransition(m.state.taskman)) if err != nil { - log.WithField("partition", env.Id().String()). - Warnf("cannot teardown environment in state %s, forcing", env.CurrentState()) + log.WithError(err). + WithField("partition", env.Id().String()). + Warnf("cannot teardown environment in state %s, going to ERROR, then forcing", env.CurrentState()) + the.EventWriterWithTopic(topic.Environment).WriteEvent( + environment.NewEnvGoErrorEvent(env, "RESET during environment destruction failed"), + ) + err = env.TryTransition(environment.NewGoErrorTransition(m.state.taskman)) + if err != nil { + environment.HandleFailedGoError(err, env) + } reply, err = m.doTeardownAndCleanup(env, true /*force*/, false /*keepTasks*/) return } From e17af39151f6be3c56ad872d80058167ee40d00b Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Mon, 3 Nov 2025 09:15:50 +0100 Subject: [PATCH 10/25] Add missing step in patch release process --- docs/development.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/development.md b/docs/development.md index 20247acc7..b9c189841 100644 --- a/docs/development.md +++ b/docs/development.md @@ -24,6 +24,7 @@ Bugs go to [JIRA](https://its.cern.ch/jira/projects/OCTRL/issues). * Checkout the tag which the patch release should be based on, e.g. `git checkout v1.34.0` * Create a branch called `branch_`, e.g. `git checkout -b branch_v1.34.1`. + * Cherry-pick desired commits 3. Bump `VERSION` file, commit, push (or pull request). 4. Go to a [new GitHub release draft](https://github.com/AliceO2Group/Control/releases/new). Use "Generate release notes" to create a list of changes. Write a short summary at the top. From 6a97d97dc9eb28e52f778b0674769b71c359edb3 Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Mon, 3 Nov 2025 09:41:08 +0100 Subject: [PATCH 11/25] Fix unexpected operator build error on POSIX shells '==' comparison operator is only supported by Bash, while '=' is supported by both Bash and standard POSIX shells. --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 58184a101..f59740768 100644 --- a/Makefile +++ b/Makefile @@ -127,7 +127,7 @@ $(WHAT): validate-go-version @$(WHAT_$@_BUILD_FLAGS) go build -mod=vendor $(VERBOSE_$(V)) -o bin/$@ $(LDFLAGS) ./cmd/$@ # special case: if the current WHAT is o2-aliecs-executor, also copy over the shmcleaner script - @if [ $@ == "o2-aliecs-executor" ]; then \ + @if [ $@ = "o2-aliecs-executor" ]; then \ echo -e "\033[1;33mcopy\033[0m ./o2-aliecs-shmcleaner \033[1;33m==>\033[0m \033[1;34m./bin/o2-aliecs-shmcleaner\033[0m"; \ cp o2-aliecs-shmcleaner bin/o2-aliecs-shmcleaner; \ chmod +x bin/o2-aliecs-shmcleaner; \ @@ -140,7 +140,7 @@ $(INSTALL_WHAT): validate-go-version @$(WHAT_$(@:install_%=%)_BUILD_FLAGS) go install -mod=vendor $(VERBOSE_$(V)) $(LDFLAGS) ./cmd/$(@:install_%=%) # special case: if the current WHAT is o2-aliecs-executor, also copy over the shmcleaner script - @if [ $@ == "install_o2-aliecs-executor" ]; then \ + @if [ $@ = "install_o2-aliecs-executor" ]; then \ echo -e "\033[1;33minstall\033[0m ./o2-aliecs-shmcleaner \033[1;33m==>\033[0m \033[1;34m$$GOPATH/bin/o2-aliecs-shmcleaner\033[0m"; \ cp o2-aliecs-shmcleaner $${GOPATH}/bin/o2-aliecs-shmcleaner; \ chmod +x $${GOPATH}/bin/o2-aliecs-shmcleaner; \ From 20f3a9313cedac8346792eabdd72ab0d921e37a4 Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Tue, 4 Nov 2025 12:05:30 +0100 Subject: [PATCH 12/25] Set special users before automatic run stops A minimal, but not comprehensive addition for OCTRL-1065. --- common/protos/common.pb.go | 138 ++++++++++++++++++++++---------- common/protos/common.proto | 9 +++ common/protos/protoutils.go | 14 ++++ core/environment/environment.go | 1 + core/environment/manager.go | 1 + 5 files changed, 122 insertions(+), 41 deletions(-) diff --git a/common/protos/common.pb.go b/common/protos/common.pb.go index 5ea0cc482..ce7796310 100644 --- a/common/protos/common.pb.go +++ b/common/protos/common.pb.go @@ -43,6 +43,58 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +// Production and staging BKP recognizes these special user IDs. +// They are used to associate certain actions (e.g. EOR) with certain subsystem +// or AliECS component rather than a human user. +type SpecialUserId int32 + +const ( + SpecialUserId_INVALID SpecialUserId = 0 + SpecialUserId_LHC SpecialUserId = 60 + SpecialUserId_TIMER SpecialUserId = 65 +) + +// Enum value maps for SpecialUserId. +var ( + SpecialUserId_name = map[int32]string{ + 0: "INVALID", + 60: "LHC", + 65: "TIMER", + } + SpecialUserId_value = map[string]int32{ + "INVALID": 0, + "LHC": 60, + "TIMER": 65, + } +) + +func (x SpecialUserId) Enum() *SpecialUserId { + p := new(SpecialUserId) + *p = x + return p +} + +func (x SpecialUserId) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (SpecialUserId) Descriptor() protoreflect.EnumDescriptor { + return file_protos_common_proto_enumTypes[0].Descriptor() +} + +func (SpecialUserId) Type() protoreflect.EnumType { + return &file_protos_common_proto_enumTypes[0] +} + +func (x SpecialUserId) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use SpecialUserId.Descriptor instead. +func (SpecialUserId) EnumDescriptor() ([]byte, []int) { + return file_protos_common_proto_rawDescGZIP(), []int{0} +} + // * // Beam modes as defined and sent by LHC DIP client plus: // * virtual type LOST_BEAMS - that is generated when beam 1 and beam 2 energy values are not equal anymore as per LHC DIP track: dip/acc/LHC/RunControl/SafeBeam @@ -138,11 +190,11 @@ func (x BeamMode) String() string { } func (BeamMode) Descriptor() protoreflect.EnumDescriptor { - return file_protos_common_proto_enumTypes[0].Descriptor() + return file_protos_common_proto_enumTypes[1].Descriptor() } func (BeamMode) Type() protoreflect.EnumType { - return &file_protos_common_proto_enumTypes[0] + return &file_protos_common_proto_enumTypes[1] } func (x BeamMode) Number() protoreflect.EnumNumber { @@ -151,7 +203,7 @@ func (x BeamMode) Number() protoreflect.EnumNumber { // Deprecated: Use BeamMode.Descriptor instead. func (BeamMode) EnumDescriptor() ([]byte, []int) { - return file_protos_common_proto_rawDescGZIP(), []int{0} + return file_protos_common_proto_rawDescGZIP(), []int{1} } type User struct { @@ -414,37 +466,40 @@ var file_protos_common_proto_rawDesc = []byte{ 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x65, 0x61, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x2c, 0x0a, 0x08, 0x62, 0x65, 0x61, 0x6d, 0x4d, 0x6f, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x10, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x42, 0x65, 0x61, 0x6d, 0x4d, 0x6f, - 0x64, 0x65, 0x52, 0x08, 0x62, 0x65, 0x61, 0x6d, 0x4d, 0x6f, 0x64, 0x65, 0x2a, 0x80, 0x03, 0x0a, - 0x08, 0x42, 0x65, 0x61, 0x6d, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, - 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x45, 0x54, 0x55, 0x50, 0x10, - 0x01, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x42, 0x4f, 0x52, 0x54, 0x10, 0x02, 0x12, 0x18, 0x0a, 0x14, - 0x49, 0x4e, 0x4a, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, - 0x42, 0x45, 0x41, 0x4d, 0x10, 0x03, 0x12, 0x18, 0x0a, 0x14, 0x49, 0x4e, 0x4a, 0x45, 0x43, 0x54, - 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x45, 0x54, 0x55, 0x50, 0x5f, 0x42, 0x45, 0x41, 0x4d, 0x10, 0x04, - 0x12, 0x1a, 0x0a, 0x16, 0x49, 0x4e, 0x4a, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x48, - 0x59, 0x53, 0x49, 0x43, 0x53, 0x5f, 0x42, 0x45, 0x41, 0x4d, 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, - 0x50, 0x52, 0x45, 0x50, 0x41, 0x52, 0x45, 0x5f, 0x52, 0x41, 0x4d, 0x50, 0x10, 0x06, 0x12, 0x08, - 0x0a, 0x04, 0x52, 0x41, 0x4d, 0x50, 0x10, 0x07, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x4c, 0x41, 0x54, - 0x5f, 0x54, 0x4f, 0x50, 0x10, 0x08, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x51, 0x55, 0x45, 0x45, 0x5a, - 0x45, 0x10, 0x09, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x44, 0x4a, 0x55, 0x53, 0x54, 0x10, 0x0a, 0x12, - 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x42, 0x45, 0x41, 0x4d, 0x53, 0x10, - 0x0b, 0x12, 0x0e, 0x0a, 0x0a, 0x4c, 0x4f, 0x53, 0x54, 0x5f, 0x42, 0x45, 0x41, 0x4d, 0x53, 0x10, - 0x0c, 0x12, 0x12, 0x0a, 0x0e, 0x55, 0x4e, 0x53, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x42, 0x45, - 0x41, 0x4d, 0x53, 0x10, 0x0d, 0x12, 0x15, 0x0a, 0x11, 0x42, 0x45, 0x41, 0x4d, 0x5f, 0x44, 0x55, - 0x4d, 0x50, 0x5f, 0x57, 0x41, 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x0e, 0x12, 0x0d, 0x0a, 0x09, - 0x42, 0x45, 0x41, 0x4d, 0x5f, 0x44, 0x55, 0x4d, 0x50, 0x10, 0x0f, 0x12, 0x0d, 0x0a, 0x09, 0x52, - 0x41, 0x4d, 0x50, 0x5f, 0x44, 0x4f, 0x57, 0x4e, 0x10, 0x10, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x59, - 0x43, 0x4c, 0x49, 0x4e, 0x47, 0x10, 0x11, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x45, 0x43, 0x4f, 0x56, - 0x45, 0x52, 0x59, 0x10, 0x12, 0x12, 0x13, 0x0a, 0x0f, 0x49, 0x4e, 0x4a, 0x45, 0x43, 0x54, 0x5f, - 0x41, 0x4e, 0x44, 0x5f, 0x44, 0x55, 0x4d, 0x50, 0x10, 0x13, 0x12, 0x16, 0x0a, 0x12, 0x43, 0x49, - 0x52, 0x43, 0x55, 0x4c, 0x41, 0x54, 0x45, 0x5f, 0x41, 0x4e, 0x44, 0x5f, 0x44, 0x55, 0x4d, 0x50, - 0x10, 0x14, 0x12, 0x0b, 0x0a, 0x07, 0x4e, 0x4f, 0x5f, 0x42, 0x45, 0x41, 0x4d, 0x10, 0x15, 0x42, - 0x53, 0x0a, 0x1f, 0x63, 0x68, 0x2e, 0x63, 0x65, 0x72, 0x6e, 0x2e, 0x61, 0x6c, 0x69, 0x63, 0x65, - 0x2e, 0x6f, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, - 0x6f, 0x6e, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x41, - 0x6c, 0x69, 0x63, 0x65, 0x4f, 0x32, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x2f, 0x43, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x73, 0x3b, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x64, 0x65, 0x52, 0x08, 0x62, 0x65, 0x61, 0x6d, 0x4d, 0x6f, 0x64, 0x65, 0x2a, 0x30, 0x0a, 0x0d, + 0x53, 0x70, 0x65, 0x63, 0x69, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x0b, 0x0a, + 0x07, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x4c, 0x48, + 0x43, 0x10, 0x3c, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x49, 0x4d, 0x45, 0x52, 0x10, 0x41, 0x2a, 0x80, + 0x03, 0x0a, 0x08, 0x42, 0x65, 0x61, 0x6d, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, + 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x45, 0x54, 0x55, + 0x50, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x42, 0x4f, 0x52, 0x54, 0x10, 0x02, 0x12, 0x18, + 0x0a, 0x14, 0x49, 0x4e, 0x4a, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x52, 0x4f, 0x42, + 0x45, 0x5f, 0x42, 0x45, 0x41, 0x4d, 0x10, 0x03, 0x12, 0x18, 0x0a, 0x14, 0x49, 0x4e, 0x4a, 0x45, + 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x45, 0x54, 0x55, 0x50, 0x5f, 0x42, 0x45, 0x41, 0x4d, + 0x10, 0x04, 0x12, 0x1a, 0x0a, 0x16, 0x49, 0x4e, 0x4a, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, + 0x50, 0x48, 0x59, 0x53, 0x49, 0x43, 0x53, 0x5f, 0x42, 0x45, 0x41, 0x4d, 0x10, 0x05, 0x12, 0x10, + 0x0a, 0x0c, 0x50, 0x52, 0x45, 0x50, 0x41, 0x52, 0x45, 0x5f, 0x52, 0x41, 0x4d, 0x50, 0x10, 0x06, + 0x12, 0x08, 0x0a, 0x04, 0x52, 0x41, 0x4d, 0x50, 0x10, 0x07, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x4c, + 0x41, 0x54, 0x5f, 0x54, 0x4f, 0x50, 0x10, 0x08, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x51, 0x55, 0x45, + 0x45, 0x5a, 0x45, 0x10, 0x09, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x44, 0x4a, 0x55, 0x53, 0x54, 0x10, + 0x0a, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x42, 0x45, 0x41, 0x4d, + 0x53, 0x10, 0x0b, 0x12, 0x0e, 0x0a, 0x0a, 0x4c, 0x4f, 0x53, 0x54, 0x5f, 0x42, 0x45, 0x41, 0x4d, + 0x53, 0x10, 0x0c, 0x12, 0x12, 0x0a, 0x0e, 0x55, 0x4e, 0x53, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, + 0x42, 0x45, 0x41, 0x4d, 0x53, 0x10, 0x0d, 0x12, 0x15, 0x0a, 0x11, 0x42, 0x45, 0x41, 0x4d, 0x5f, + 0x44, 0x55, 0x4d, 0x50, 0x5f, 0x57, 0x41, 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x0e, 0x12, 0x0d, + 0x0a, 0x09, 0x42, 0x45, 0x41, 0x4d, 0x5f, 0x44, 0x55, 0x4d, 0x50, 0x10, 0x0f, 0x12, 0x0d, 0x0a, + 0x09, 0x52, 0x41, 0x4d, 0x50, 0x5f, 0x44, 0x4f, 0x57, 0x4e, 0x10, 0x10, 0x12, 0x0b, 0x0a, 0x07, + 0x43, 0x59, 0x43, 0x4c, 0x49, 0x4e, 0x47, 0x10, 0x11, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x45, 0x43, + 0x4f, 0x56, 0x45, 0x52, 0x59, 0x10, 0x12, 0x12, 0x13, 0x0a, 0x0f, 0x49, 0x4e, 0x4a, 0x45, 0x43, + 0x54, 0x5f, 0x41, 0x4e, 0x44, 0x5f, 0x44, 0x55, 0x4d, 0x50, 0x10, 0x13, 0x12, 0x16, 0x0a, 0x12, + 0x43, 0x49, 0x52, 0x43, 0x55, 0x4c, 0x41, 0x54, 0x45, 0x5f, 0x41, 0x4e, 0x44, 0x5f, 0x44, 0x55, + 0x4d, 0x50, 0x10, 0x14, 0x12, 0x0b, 0x0a, 0x07, 0x4e, 0x4f, 0x5f, 0x42, 0x45, 0x41, 0x4d, 0x10, + 0x15, 0x42, 0x53, 0x0a, 0x1f, 0x63, 0x68, 0x2e, 0x63, 0x65, 0x72, 0x6e, 0x2e, 0x61, 0x6c, 0x69, + 0x63, 0x65, 0x2e, 0x6f, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x63, 0x6f, + 0x6d, 0x6d, 0x6f, 0x6e, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x41, 0x6c, 0x69, 0x63, 0x65, 0x4f, 0x32, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x2f, 0x43, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x73, 0x3b, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -459,16 +514,17 @@ func file_protos_common_proto_rawDescGZIP() []byte { return file_protos_common_proto_rawDescData } -var file_protos_common_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_protos_common_proto_enumTypes = make([]protoimpl.EnumInfo, 2) var file_protos_common_proto_msgTypes = make([]protoimpl.MessageInfo, 3) var file_protos_common_proto_goTypes = []interface{}{ - (BeamMode)(0), // 0: common.BeamMode - (*User)(nil), // 1: common.User - (*WorkflowTemplateInfo)(nil), // 2: common.WorkflowTemplateInfo - (*BeamInfo)(nil), // 3: common.BeamInfo + (SpecialUserId)(0), // 0: common.SpecialUserId + (BeamMode)(0), // 1: common.BeamMode + (*User)(nil), // 2: common.User + (*WorkflowTemplateInfo)(nil), // 3: common.WorkflowTemplateInfo + (*BeamInfo)(nil), // 4: common.BeamInfo } var file_protos_common_proto_depIdxs = []int32{ - 0, // 0: common.BeamInfo.beamMode:type_name -> common.BeamMode + 1, // 0: common.BeamInfo.beamMode:type_name -> common.BeamMode 1, // [1:1] is the sub-list for method output_type 1, // [1:1] is the sub-list for method input_type 1, // [1:1] is the sub-list for extension type_name @@ -525,7 +581,7 @@ func file_protos_common_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_protos_common_proto_rawDesc, - NumEnums: 1, + NumEnums: 2, NumMessages: 3, NumExtensions: 0, NumServices: 0, diff --git a/common/protos/common.proto b/common/protos/common.proto index f367be9e4..1942c36e2 100644 --- a/common/protos/common.proto +++ b/common/protos/common.proto @@ -40,6 +40,15 @@ message User { string name = 3; } +// Production and staging BKP recognizes these special user IDs. +// They are used to associate certain actions (e.g. EOR) with certain subsystem +// or AliECS component rather than a human user. +enum SpecialUserId { + INVALID = 0; + LHC = 60; + TIMER = 65; +} + message WorkflowTemplateInfo { string name = 1; string description = 2; diff --git a/common/protos/protoutils.go b/common/protos/protoutils.go index e0a009de5..5d3a43d82 100644 --- a/common/protos/protoutils.go +++ b/common/protos/protoutils.go @@ -34,3 +34,17 @@ func WrapEvent(ce isEvent_Payload) *Event { Payload: ce, } } + +// SpecialUser returns a User populated from a SpecialUserId enum: +// - externalId = enum numeric value +// - id = enum numeric value +// - name = enum string name +func SpecialUser(enumId SpecialUserId) *User { + externalId := int32(enumId) + name := enumId.String() + return &User{ + ExternalId: &externalId, + Id: nil, + Name: name, + } +} diff --git a/core/environment/environment.go b/core/environment/environment.go index e42620093..fcdac227e 100644 --- a/core/environment/environment.go +++ b/core/environment/environment.go @@ -1449,6 +1449,7 @@ func (env *Environment) scheduleAutoStopTransition() (scheduled bool, expected t log.WithField("partition", env.id). WithField("run", env.currentRunNumber). Infof("Executing scheduled auto stop transition following expiration of %s", autoStopDuration) + env.SetLastRequestUser(pb.SpecialUser(pb.SpecialUserId_TIMER)) err = env.TryTransition(NewStopActivityTransition(ManagerInstance().taskman)) if err != nil { log.WithField("partition", env.id). diff --git a/core/environment/manager.go b/core/environment/manager.go index c494e90fe..33ad5c098 100644 --- a/core/environment/manager.go +++ b/core/environment/manager.go @@ -1103,6 +1103,7 @@ func (envs *Manager) handleLhcEvents(evt event.IntegratedServiceEvent) { WithField("run", env.currentRunNumber). Info("stopping the run due to beam dump") + env.SetLastRequestUser(evpb.SpecialUser(evpb.SpecialUserId_LHC)) err := env.TryTransition(NewStopActivityTransition(envs.taskman)) if err != nil { log.WithPrefix("scheduler"). From fee4e3416ac778156d02b0a42f98287c2a20cb10 Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Thu, 6 Nov 2025 09:59:07 +0100 Subject: [PATCH 13/25] Add a copilot guidelines for avoiding unobvious abbreviations and acronyms --- .github/copilot-instructions.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index afa8b0e12..fb7011437 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -14,4 +14,5 @@ It is a distributed system that combines state of the art cluster resource manag - Do not include modified go.mod and go.sum files in your commits unless you are adding or upgrading a dependency. - When adding features or fixing bugs, add a corresponding unit test if feasible. Use Ginkgo/Gomega, unless a package already uses a different testing framework. - When adding a new feature, extend the documentation accordingly, follow the existing style and structure, and make sure that Tables of Contents are updated. See [Documentation guidelines](docs/CONTRIBUTING.md#documentation-guidelines) for some more details. -- When providing a fix, explain what was causing the issue and how it was fixed. \ No newline at end of file +- When providing a fix, explain what was causing the issue and how it was fixed. +- Avoid using abbreviations and acronyms for variable and function names. They are acceptable if they are commonly used in a given domain, such as "cfg" for "configura +++tion" or "LHC" for "Large Hadron Collider". From 365efca584f1722b0406d077b8b23f5c28e6e20d Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Mon, 10 Nov 2025 10:51:50 +0100 Subject: [PATCH 14/25] Improvements in logging failures of auto-environments - Environment failure is reported as an Error, not Warn - we simplify "MesosCommand_Transition timed out for task 2xhyfnmHttq" to "Transition timed out", so the full error is more readable. For examplewq "Transition canceled with error: CONFIGURE could not complete for critical tasks, errors: task 'readout' on alio2-cr1-mvs03 (id 2y3E83DDK6E) failed with error: Transition timed out; task 'stfb' on alio2-cr1-mvs03 (id 2y3E83DDeaA) failed with error: Transition timed out; task 'stfs' on alio2-cr1-mvs03 (id 2y3E83DDz46) failed with error: Transition timed out" Closes OCTRL-1059. --- core/controlcommands/mesoscommandservent.go | 4 +++- core/environment/manager.go | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/core/controlcommands/mesoscommandservent.go b/core/controlcommands/mesoscommandservent.go index 2185eea2e..4eded55eb 100644 --- a/core/controlcommands/mesoscommandservent.go +++ b/core/controlcommands/mesoscommandservent.go @@ -26,6 +26,7 @@ package controlcommands import ( "fmt" + "strings" "sync" "time" @@ -144,7 +145,8 @@ func (s *Servent) RunCommand(cmd MesosCommand, receiver MesosCommandTarget) (Mes // By the time we get here, ProcessResponse should have already added a Response to the // pending call, and removed it from servent.pending. case <-time.After(cmd.GetResponseTimeout()): - call.Error = fmt.Errorf("%s timed out for task %s", cmd.GetName(), receiver.TaskId.Value) + userFriendlyCommandName, _ := strings.CutPrefix(cmd.GetName(), "MesosCommand_") + call.Error = fmt.Errorf("%s timed out", userFriendlyCommandName) log.WithPrefix("servent"). WithField("partition", cmd.GetEnvironmentId().String()). diff --git a/core/environment/manager.go b/core/environment/manager.go index 33ad5c098..8546bd0c9 100644 --- a/core/environment/manager.go +++ b/core/environment/manager.go @@ -487,7 +487,7 @@ func (envs *Manager) CreateEnvironment(workflowPath string, userVars map[string] log.WithField("state", envState). WithField("partition", env.Id().String()). WithError(err). - Warnf("auto-transitioning environment failed %s, cleanup in progress", op) + Errorf("auto-transitioning environment failed %s, cleanup in progress", op) the.EventWriterWithTopic(topic.Environment).WriteEvent( NewEnvGoErrorEvent(env, fmt.Sprintf("%s failed: %v", op, err)), @@ -1460,7 +1460,7 @@ func (envs *Manager) CreateAutoEnvironment(workflowPath string, userVars map[str log.WithField("state", envState). WithField("partition", env.Id().String()). WithError(err). - Warnf("auto-transitioning environment failed %s, cleanup in progress", op) + Errorf("auto-transitioning environment failed %s, cleanup in progress", op) the.EventWriterWithTopic(topic.Environment).WriteEvent( NewEnvGoErrorEvent(env, fmt.Sprintf("%s failed: %v", op, err)), From 9258177dfa85fca41b7d4175a66d431fe4f015a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Tich=C3=A1k?= Date: Fri, 31 Oct 2025 09:53:48 +0100 Subject: [PATCH 15/25] [monitoring] Refactor monitoring so Send doesn't have to wait until library is running --- common/monitoring/monitoring.go | 77 +++++++++++++++------------- common/monitoring/monitoring_test.go | 18 ++----- core/core.go | 5 ++ 3 files changed, 51 insertions(+), 49 deletions(-) diff --git a/common/monitoring/monitoring.go b/common/monitoring/monitoring.go index 91dbd417f..f64339bdb 100644 --- a/common/monitoring/monitoring.go +++ b/common/monitoring/monitoring.go @@ -42,50 +42,38 @@ var ( // atomic holder for the HTTP server instance server atomic.Pointer[http.Server] // objects to store incoming metrics - metricsInternal *MetricsAggregate - metricsHistogramInternal *MetricsReservoirSampling + metricsInternal *MetricsAggregate = NewMetricsAggregate() + metricsHistogramInternal *MetricsReservoirSampling = NewMetricsReservoirSampling() // channel that is used to request end of metrics server, it sends notification when server ended. // It needs to be read!!! - endChannel chan struct{} + endChannel chan struct{} = make(chan struct{}) // channel used to send metrics into the event loop - metricsChannel chan Metric + // 100000 was chosen arbitrarily as a number that seemed sensible to be high enough to provide nice buffer if + // multiple goroutines want to send metrics without blocking each other + metricsChannel chan Metric = make(chan Metric, 100000) // channel used to send metrics meant to be proceesed as histogram into the event loop - metricsHistosChannel chan Metric + // 100000 was chosen arbitrarily as a number that seemed sensible to be high enough to provide nice buffer if + // multiple goroutines want to send metrics without blocking each other + metricsHistosChannel chan Metric = make(chan Metric, 100000) // channel for sending requests to reset actual metrics slice and send it back to caller via metricsExportedToRequest - metricsRequestedChannel chan struct{} + metricsRequestedChannel chan struct{} = make(chan struct{}) // channel used to send metrics to be reported by http request from event loop - metricsExportedToRequest chan []Metric + metricsExportedToRequest chan []Metric = make(chan []Metric) - log = logger.New(logrus.StandardLogger(), "metrics").WithField("level", infologger.IL_Devel) -) - -func initChannels() { - endChannel = make(chan struct{}) - metricsRequestedChannel = make(chan struct{}) - // 100 was chosen arbitrarily as a number that seemed sensible to be high enough to provide nice buffer if - // multiple goroutines want to send metrics without blocking each other - metricsChannel = make(chan Metric, 100000) - metricsHistosChannel = make(chan Metric, 100000) - metricsExportedToRequest = make(chan []Metric) - metricsInternal = NewMetricsAggregate() - metricsHistogramInternal = NewMetricsReservoirSampling() -} + // WaitUntilRunning is waiting until this channel is closed + waitUntilRunningChannel chan struct{} = make(chan struct{}) -func closeChannels() { - close(endChannel) - close(metricsRequestedChannel) - close(metricsChannel) - close(metricsExportedToRequest) -} + log = logger.New(logrus.StandardLogger(), "metrics").WithField(infologger.Level, infologger.IL_Devel) +) // this eventLoop is the main part that processes all metrics send to the package // 4 events can happen: -// 1. metricsChannel receives message from Send() method. We just add the new metric to metrics slice -// 2. metricsHistosChannel receives message from Send() method. We just add the new metric to metrics slice +// 1. metricsChannel receives message from Send() method. We add the new metric to metrics slice +// 2. metricsHistosChannel receives message from Send() method. We add the new metric to metrics slice // 3. metricsRequestChannel receives request to dump and request existing metrics. We send shallow copy of existing // metrics to requestor (via metricsExportedToRequest channel) while resetting current metrics slice // 4. receive request to stop monitoring via endChannel. We send confirmation through endChannel to notify caller @@ -130,14 +118,18 @@ func exportMetricsAndReset(w http.ResponseWriter, r *http.Request) { } func Send(metric *Metric) { - if IsRunning() { - metricsChannel <- *metric + // drop overflowing messages to not slowdown processing, we don't log so we don't flood IL + select { + case metricsChannel <- *metric: + default: } } func SendHistogrammable(metric *Metric) { - if IsRunning() { - metricsHistosChannel <- *metric + // drop overflowing messages to not slowdown processing, we don't log so we don't flood IL + select { + case metricsHistosChannel <- *metric: + default: } } @@ -160,10 +152,10 @@ func Run(port uint16, endpointName string) error { if !server.CompareAndSwap(nil, localServer) { return nil } - initChannels() go eventLoop() handleFunc(endpointName) // block until Shutdown is called + close(waitUntilRunningChannel) return localServer.ListenAndServe() } @@ -176,9 +168,22 @@ func Stop() { defer cancel() localServer.Shutdown(ctx) endChannel <- struct{}{} + _, ok := <-waitUntilRunningChannel + if !ok { + waitUntilRunningChannel = make(chan struct{}) + } <-endChannel } -func IsRunning() bool { - return server.Load() != nil +// If monitoring is not running it will wait until monitoring is running or +// timeout is triggered. +// \return true if monitoring is running, false if timeout occured +func WaitUntilRunning(timeout time.Duration) bool { + timeoutChan := time.After(timeout) + select { + case <-waitUntilRunningChannel: + return true + case <-timeoutChan: + return false + } } diff --git a/common/monitoring/monitoring_test.go b/common/monitoring/monitoring_test.go index b0da38435..dd98cf6b8 100644 --- a/common/monitoring/monitoring_test.go +++ b/common/monitoring/monitoring_test.go @@ -40,16 +40,8 @@ import ( // blocks until either IsRunning() returns true or timeout is triggered func isRunningWithTimeout(t *testing.T, timeout time.Duration) { - timeoutChan := time.After(timeout) - for !IsRunning() { - select { - case <-timeoutChan: - t.Errorf("Monitoring is not running even after %v", timeout) - return - - default: - time.Sleep(10 * time.Millisecond) - } + if !WaitUntilRunning(timeout) { + t.Errorf("Failed to init monitoring library in %v", timeout) } } @@ -126,7 +118,7 @@ func TestHttpRun(t *testing.T) { go Run(9876, "/metrics") defer Stop() - isRunningWithTimeout(t, time.Second) + isRunningWithTimeout(t, 5*time.Second) metric := Metric{name: "test"} metric.timestamp = time.Unix(10, 0) @@ -140,12 +132,12 @@ func TestHttpRun(t *testing.T) { } message, err := io.ReadAll(response.Body) if err != nil { - t.Errorf("Failed to read response Body: %v", err) + t.Fatalf("Failed to read response Body: %v", err) } receivedMetrics, err := parseMultipleLineProtocol(string(message)) if err != nil { - t.Errorf("Failed to parse message: %v", string(message)) + t.Fatalf("Failed to parse message: %v with err: %v", string(message), err) } receivedMetric := receivedMetrics[0] diff --git a/core/core.go b/core/core.go index 6919cb45c..f2370f11b 100644 --- a/core/core.go +++ b/core/core.go @@ -90,6 +90,11 @@ func runMetrics() { } }() + monitoringTimeout := 30 * time.Second + if !monitoring.WaitUntilRunning(monitoringTimeout) { + log.WithField(infologger.Level, infologger.IL_Devel).Warnf("Failed to initialize monitoring framework in %v, it might catch up later. For now we are starting without metrics", monitoringTimeout) + } + golangmetrics.Start(10 * time.Second) } From 39494636ed2f327de1cf40bbd7aba27a591282de Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Thu, 6 Nov 2025 09:52:13 +0100 Subject: [PATCH 16/25] Drain backlog LHC events and load current fill info upon startup When AliECS core starts, We are not interested in old events except of the latest, so we know the current beam conditions. This works will allow us to get rid of BKP.RetrieveFillInfo() and have a corresponding update call in the LHC plugin. Closes OCTRL-1067. --- common/event/reader.go | 151 +++++++++++++++++++++++++-------- core/integration/lhc/plugin.go | 74 +++++++++++++--- 2 files changed, 176 insertions(+), 49 deletions(-) diff --git a/common/event/reader.go b/common/event/reader.go index 0b348cafc..f163e692e 100644 --- a/common/event/reader.go +++ b/common/event/reader.go @@ -27,44 +27,42 @@ package event import ( "context" "fmt" + "github.com/AliceO2Group/Control/common/event/topic" "github.com/AliceO2Group/Control/common/logger/infologger" pb "github.com/AliceO2Group/Control/common/protos" "github.com/segmentio/kafka-go" "github.com/spf13/viper" "google.golang.org/protobuf/proto" - "sync" ) // Reader interface provides methods to read events. type Reader interface { + // Next should return the next event or cancel if the context is cancelled. Next(ctx context.Context) (*pb.Event, error) + // Last should return the last available event currently present on the topic (or nil if none) + // or cancel if the context is cancelled. + Last(ctx context.Context) (*pb.Event, error) Close() error } // DummyReader is an implementation of Reader that returns no events. type DummyReader struct{} -// Next returns the next event or nil if there are no more events. func (*DummyReader) Next(context.Context) (*pb.Event, error) { return nil, nil } - -// Close closes the DummyReader. -func (*DummyReader) Close() error { return nil } +func (*DummyReader) Last(context.Context) (*pb.Event, error) { return nil, nil } +func (*DummyReader) Close() error { return nil } // KafkaReader reads events from Kafka and provides a blocking, cancellable API to fetch events. -// Consumption mode is chosen at creation time: -// - latestOnly=false: consume everything (from stored offsets or beginning depending on group state) -// - latestOnly=true: seek to latest offsets on start and only receive messages produced after start type KafkaReader struct { *kafka.Reader - mu sync.Mutex - topic string + topic string + brokers []string + groupID string } // NewReaderWithTopic creates a KafkaReader for the provided topic and starts it. -// If latestOnly is true the reader attempts to seek to the latest offsets on start so that -// only new messages (produced after creation) are consumed. -func NewReaderWithTopic(topic topic.Topic, groupID string, latestOnly bool) *KafkaReader { +func NewReaderWithTopic(topic topic.Topic, groupID string) *KafkaReader { cfg := kafka.ReaderConfig{ Brokers: viper.GetStringSlice("kafkaEndpoints"), Topic: string(topic), @@ -74,39 +72,72 @@ func NewReaderWithTopic(topic topic.Topic, groupID string, latestOnly bool) *Kaf } rk := &KafkaReader{ - Reader: kafka.NewReader(cfg), - topic: string(topic), - } - - if latestOnly { - // best-effort: set offset to last so we don't replay older messages - if err := rk.SetOffset(kafka.LastOffset); err != nil { - log.WithField(infologger.Level, infologger.IL_Devel). - Warnf("failed to set offset to last offset: %v", err) - } + Reader: kafka.NewReader(cfg), + topic: string(topic), + brokers: append([]string{}, cfg.Brokers...), + groupID: groupID, } - return rk } -// Next blocks until the next event is available or ctx is cancelled. It returns an error when the reader is closed -// (io.EOF) or the context is cancelled. The caller is responsible for providing a cancellable ctx. +// Next blocks until the next event is available or ctx is cancelled. func (r *KafkaReader) Next(ctx context.Context) (*pb.Event, error) { if r == nil { return nil, fmt.Errorf("nil reader") } - msg, err := r.ReadMessage(ctx) if err != nil { return nil, err } + return kafkaMessageToEvent(msg) +} - event, err := kafkaMessageToEvent(msg) +// Last fetches the last available message on the topic (considering all partitions). +// If multiple partitions have data, the event with the greatest message timestamp is returned. +func (r *KafkaReader) Last(ctx context.Context) (*pb.Event, error) { + if r == nil { + return nil, fmt.Errorf("nil reader") + } + partitions, err := r.readPartitions() if err != nil { return nil, err } - - return event, nil + var latestEvt *pb.Event + var latestEvtTimeNs int64 + for _, p := range partitions { + if p.Topic != r.topic { + continue + } + first, last, err := r.readFirstAndLast(p.ID) + if err != nil { + log.WithField(infologger.Level, infologger.IL_Devel).WithError(err). + Warnf("failed to read offsets for %s[%d]", r.topic, p.ID) + continue + } + if last <= first { + continue + } + msg, err := r.readAtOffset(ctx, p.ID, last-1) + if err != nil { + log.WithError(err). + WithField(infologger.Level, infologger.IL_Devel). + Warnf("failed to read last message for %s[%d] at offset %d", r.topic, p.ID, last-1) + continue + } + evt, err := kafkaMessageToEvent(msg) + if err != nil { + log.WithError(err). + WithField(infologger.Level, infologger.IL_Devel). + Warnf("failed to decode last message for %s[%d]", r.topic, p.ID) + continue + } + currentEvtTimeNs := msg.Time.UnixNano() + if latestEvt == nil || currentEvtTimeNs > latestEvtTimeNs { + latestEvt = evt + latestEvtTimeNs = currentEvtTimeNs + } + } + return latestEvt, nil } // Close stops the reader. @@ -114,13 +145,7 @@ func (r *KafkaReader) Close() error { if r == nil { return nil } - // Close the underlying kafka reader which will cause ReadMessage to return an error - err := r.Reader.Close() - if err != nil { - log.WithField(infologger.Level, infologger.IL_Devel). - Errorf("failed to close kafka reader: %v", err) - } - return err + return r.Reader.Close() } func kafkaMessageToEvent(m kafka.Message) (*pb.Event, error) { @@ -130,3 +155,55 @@ func kafkaMessageToEvent(m kafka.Message) (*pb.Event, error) { } return &evt, nil } + +func (r *KafkaReader) brokerAddr() (string, error) { + if len(r.brokers) == 0 { + return "", fmt.Errorf("no kafka brokers configured") + } + return r.brokers[0], nil +} + +func (r *KafkaReader) readPartitions() ([]kafka.Partition, error) { + addr, err := r.brokerAddr() + if err != nil { + return nil, err + } + conn, err := kafka.Dial("tcp", addr) + if err != nil { + return nil, err + } + defer conn.Close() + return conn.ReadPartitions(r.topic) +} + +func (r *KafkaReader) readFirstAndLast(partition int) (int64, int64, error) { + addr, err := r.brokerAddr() + if err != nil { + return 0, 0, err + } + conn, err := kafka.DialLeader(context.Background(), "tcp", addr, r.topic, partition) + if err != nil { + return 0, 0, err + } + defer conn.Close() + first, last, err := conn.ReadOffsets() + return first, last, err +} + +func (r *KafkaReader) readAtOffset(ctx context.Context, partition int, offset int64) (kafka.Message, error) { + if offset < 0 { + return kafka.Message{}, fmt.Errorf("invalid offset %d", offset) + } + kr := kafka.NewReader(kafka.ReaderConfig{ + Brokers: append([]string{}, r.brokers...), + Topic: r.topic, + Partition: partition, + MinBytes: 1, + MaxBytes: 10e6, + }) + defer kr.Close() + if err := kr.SetOffset(offset); err != nil { + return kafka.Message{}, err + } + return kr.ReadMessage(ctx) +} diff --git a/core/integration/lhc/plugin.go b/core/integration/lhc/plugin.go index 1d5853d91..28cbcc74e 100644 --- a/core/integration/lhc/plugin.go +++ b/core/integration/lhc/plugin.go @@ -28,16 +28,16 @@ import ( "context" "encoding/json" "errors" - "github.com/AliceO2Group/Control/common/event/topic" - "github.com/AliceO2Group/Control/common/logger/infologger" - pb "github.com/AliceO2Group/Control/common/protos" "io" "strings" "sync" "time" cmnevent "github.com/AliceO2Group/Control/common/event" + "github.com/AliceO2Group/Control/common/event/topic" "github.com/AliceO2Group/Control/common/logger" + "github.com/AliceO2Group/Control/common/logger/infologger" + pb "github.com/AliceO2Group/Control/common/protos" "github.com/AliceO2Group/Control/common/utils/uid" "github.com/AliceO2Group/Control/core/environment" "github.com/AliceO2Group/Control/core/integration" @@ -51,10 +51,8 @@ var dipClientTopic topic.Topic = "dip.lhc.beam_mode" // Plugin implements integration.Plugin and listens for LHC updates. type Plugin struct { - endpoint string - ctx context.Context - //cancel context.CancelFunc - //wg sync.WaitGroup + endpoint string + ctx context.Context mu sync.Mutex currentState *pb.BeamInfo reader cmnevent.Reader @@ -66,21 +64,73 @@ func NewPlugin(endpoint string) integration.Plugin { } func (p *Plugin) Init(_ string) error { - // use a background context for reader loop; Destroy will Close the reader p.ctx = context.Background() - p.reader = cmnevent.NewReaderWithTopic(dipClientTopic, "o2-aliecs-core.lhc", true) - + p.reader = cmnevent.NewReaderWithTopic(dipClientTopic, "o2-aliecs-core.lhc") if p.reader == nil { return errors.New("could not create a kafka reader for LHC plugin") } - go p.readAndInjectLhcUpdates() - log.Debug("LHC plugin initialized (client started)") + // Always perform a short pre-drain to consume any backlog without injecting. + log.WithField(infologger.Level, infologger.IL_Devel). + Info("LHC plugin: draining any initial backlog") + p.drainBacklog(2 * time.Second) + + // If state is still empty, try reading the latest message once. + p.mu.Lock() + empty := p.currentState == nil || p.currentState.BeamMode == pb.BeamMode_UNKNOWN + p.mu.Unlock() + if empty { + if last, err := p.reader.Last(p.ctx); err != nil { + log.WithField(infologger.Level, infologger.IL_Support).WithError(err).Warn("failed to read last LHC state on init") + } else if last != nil { + if bmEvt := last.GetBeamModeEvent(); bmEvt != nil && bmEvt.GetBeamInfo() != nil { + p.mu.Lock() + p.currentState = bmEvt.GetBeamInfo() + p.mu.Unlock() + } + } else { + // nothing to retrieve in the topic, we move on + } + } + + go p.readAndInjectLhcUpdates() + log.WithField(infologger.Level, infologger.IL_Devel).Debug("LHC plugin initialized (client started)") return nil } +// drainBacklog reads messages for a limited time and only updates the plugin state, without injecting to env manager. +func (p *Plugin) drainBacklog(timeout time.Duration) { + drainCtx, cancel := context.WithTimeout(p.ctx, timeout) + defer cancel() + for { + msg, err := p.reader.Next(drainCtx) + if err != nil { + if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, io.EOF) || errors.Is(err, context.Canceled) { + break + } + // transient error: small sleep and continue until timeout + time.Sleep(50 * time.Millisecond) + continue + } + if msg == nil { + continue + } + if beamModeEvent := msg.GetBeamModeEvent(); beamModeEvent != nil && beamModeEvent.GetBeamInfo() != nil { + beamInfo := beamModeEvent.GetBeamInfo() + log.WithField(infologger.Level, infologger.IL_Devel). + Debugf("new LHC update received while draining backlog: BeamMode=%s, FillNumber=%d, FillingScheme=%s, StableBeamsStart=%d, StableBeamsEnd=%d, BeamType=%s", + beamInfo.GetBeamMode().String(), beamInfo.GetFillNumber(), beamInfo.GetFillingSchemeName(), + beamInfo.GetStableBeamsStart(), beamInfo.GetStableBeamsEnd(), beamInfo.GetBeamType()) + + p.mu.Lock() + p.currentState = beamModeEvent.GetBeamInfo() + p.mu.Unlock() + } + } +} + func (p *Plugin) GetName() string { return "lhc" } func (p *Plugin) GetPrettyName() string { return "LHC (DIP/Kafka client)" } func (p *Plugin) GetEndpoint() string { From 87f06096b21cab233f71311e48828631ad27a1d5 Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Mon, 3 Nov 2025 14:44:21 +0100 Subject: [PATCH 17/25] Migrate fill info retrieval to the new LHC plugin This commit adds a new call in LHC plugin which updates a given environment with the latest known fill information. Once we validate it, we can proceed with switching off the bkp.RetrieveFillInfo() call. A necessary change in workflow template will have to follow. This approach is better, because we don't rely on a man in the middle, thus reduce risks of errors and getting the required info too late (i.e. not before SOR). Closes OCTRL-1057 --- core/environment/transition_startactivity.go | 1 - core/integration/lhc/plugin.go | 96 +++++++++++++++++++- docs/handbook/operation_order.md | 3 +- 3 files changed, 96 insertions(+), 4 deletions(-) diff --git a/core/environment/transition_startactivity.go b/core/environment/transition_startactivity.go index 86f13cbad..21c6ec9ec 100644 --- a/core/environment/transition_startactivity.go +++ b/core/environment/transition_startactivity.go @@ -81,7 +81,6 @@ func (t StartActivityTransition) do(env *Environment) (err error) { // Get a handle to the consolidated var stack of the root role of the env's workflow if wf := env.Workflow(); wf != nil { if cvs, cvsErr := wf.ConsolidatedVarStack(); cvsErr == nil { - // If bookkeeping is enabled and has fetched the LHC fill info, we can acquire it here for _, key := range []string{ "fill_info_fill_number", "fill_info_filling_scheme", diff --git a/core/integration/lhc/plugin.go b/core/integration/lhc/plugin.go index 28cbcc74e..ed9f01e25 100644 --- a/core/integration/lhc/plugin.go +++ b/core/integration/lhc/plugin.go @@ -29,6 +29,7 @@ import ( "encoding/json" "errors" "io" + "strconv" "strings" "sync" "time" @@ -42,6 +43,7 @@ import ( "github.com/AliceO2Group/Control/core/environment" "github.com/AliceO2Group/Control/core/integration" lhcevent "github.com/AliceO2Group/Control/core/integration/lhc/event" + "github.com/AliceO2Group/Control/core/workflow/callable" "github.com/sirupsen/logrus" "github.com/spf13/viper" ) @@ -175,8 +177,18 @@ func (p *Plugin) GetEnvironmentsShortData(envIds []uid.ID) map[uid.ID]string { func (p *Plugin) ObjectStack(_ map[string]string, _ map[string]string) (stack map[string]interface{}) { return make(map[string]interface{}) } -func (p *Plugin) CallStack(_ interface{}) (stack map[string]interface{}) { - return make(map[string]interface{}) +func (p *Plugin) CallStack(data interface{}) (stack map[string]interface{}) { + call, ok := data.(*callable.Call) + if !ok { + return + } + + stack = make(map[string]interface{}) + stack["UpdateFillInfo"] = func() (out string) { + p.updateFillInfo(call) + return + } + return } func (p *Plugin) Destroy() error { @@ -248,3 +260,83 @@ func (p *Plugin) readAndInjectLhcUpdates() { } } } + +// UpdateFillInfo: propagate latest LHC fill info into the environment's global runtime vars +func (p *Plugin) updateFillInfo(call *callable.Call) (out string) { + varStack := call.VarStack + envId, ok := varStack["environment_id"] + if !ok { + err := errors.New("cannot acquire environment ID") + log.Error(err) + + call.VarStack["__call_error_reason"] = err.Error() + call.VarStack["__call_error"] = "LHC plugin Call Stack failed" + return + } + + log := log.WithFields(logrus.Fields{ + "partition": envId, + "call": "UpdateFillInfo", + }) + + parentRole, ok := call.GetParentRole().(callable.ParentRole) + if !ok || parentRole == nil { + log.WithField(infologger.Level, infologger.IL_Support). + Error("cannot access parent role to propagate LHC fill info") + return + } + + if p.currentState == nil { + log.WithField(infologger.Level, infologger.IL_Support). + Warn("attempted to update environment with fill info, but fill info is not available in plugin") + return + } + + // note: the following was causing very weird behaviours, which could be attributed to memory corruption. + // I did not manage to understand why can't we safely clone such a proto message. + // state := proto.Clone(p.currentState).(*pb.BeamInfo) + + p.mu.Lock() + defer p.mu.Unlock() + state := p.currentState + + parentRole.SetGlobalRuntimeVar("fill_info_beam_mode", state.BeamMode.String()) + + // If NO_BEAM, clear all other fill info and return + if state.BeamMode == pb.BeamMode_NO_BEAM { + parentRole.DeleteGlobalRuntimeVar("fill_info_fill_number") + parentRole.DeleteGlobalRuntimeVar("fill_info_filling_scheme") + parentRole.DeleteGlobalRuntimeVar("fill_info_beam_type") + parentRole.DeleteGlobalRuntimeVar("fill_info_stable_beam_start_ms") + parentRole.DeleteGlobalRuntimeVar("fill_info_stable_beam_end_ms") + + log.WithField(infologger.Level, infologger.IL_Devel). + Debug("NO_BEAM — cleared fill info vars and set beam mode only") + return + } + + // Otherwise, propagate latest known info + parentRole.SetGlobalRuntimeVar("fill_info_fill_number", strconv.FormatInt(int64(state.FillNumber), 10)) + parentRole.SetGlobalRuntimeVar("fill_info_filling_scheme", state.FillingSchemeName) + parentRole.SetGlobalRuntimeVar("fill_info_beam_type", state.BeamType) + if state.StableBeamsStart > 0 { + parentRole.SetGlobalRuntimeVar("fill_info_stable_beam_start_ms", strconv.FormatInt(state.StableBeamsStart, 10)) + } else { + parentRole.DeleteGlobalRuntimeVar("fill_info_stable_beam_start_ms") + } + if state.StableBeamsEnd > 0 { + parentRole.SetGlobalRuntimeVar("fill_info_stable_beam_end_ms", strconv.FormatInt(state.StableBeamsEnd, 10)) + } else { + parentRole.DeleteGlobalRuntimeVar("fill_info_stable_beam_end_ms") + } + + log.WithField("fillNumber", state.FillNumber). + WithField("fillingScheme", state.FillingSchemeName). + WithField("beamType", state.BeamType). + WithField("beamMode", state.BeamMode). + WithField("stableStartMs", state.StableBeamsStart). + WithField("stableEndMs", state.StableBeamsEnd). + WithField(infologger.Level, infologger.IL_Devel). + Debug("updated environment fill info from latest snapshot") + return +} diff --git a/docs/handbook/operation_order.md b/docs/handbook/operation_order.md index cd81e77ee..7f1ef830d 100644 --- a/docs/handbook/operation_order.md +++ b/docs/handbook/operation_order.md @@ -32,11 +32,11 @@ This is the order of actions happening at a healthy start of run. - `before_START_ACTIVITY` hooks with negative weights are executed: - `trg.PrepareForRun()` at `-200` + - `lhc.UpdateFillInfo()` at `-50` - `"run_number"` is set. - `"run_start_time_ms"` is set using the current time. It is considered as the SOR and SOSOR timestamps. - `before_START_ACTIVITY` hooks with positive weights (incl. 0) are executed: - `trg.RunLoad()`, `bookkeeping.StartOfRun()` at `10` - - `bookkeeping.RetrieveFillInfo()` at `11` - `kafka.PublishStartActivityUpdate()` at `50` - `dcs.StartOfRun()`, `odc.Start()` (does not need to return now), `ccdb.RunStart()` at `100` @@ -72,6 +72,7 @@ This is the order of actions happening at a healthy end of run. ### before_STOP_ACTIVITY - `before_STOP_ACTIVITY` hooks with negative weights are executed + - `lhc.UpdateFillInfo()` at `-50` - `trg.RunStop()` at `-10` - `"run_end_time_ms"` is set using the current time. It is considered as the EOR and SOEOR timestamps. - `before_STOP_ACTIVITY` hooks with positive weights (incl. 0) are executed: From 832ed65b64adc263c76c1526a3987fe130b6621d Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Thu, 20 Nov 2025 16:48:09 +0100 Subject: [PATCH 18/25] Rename stable_beam to stable_beams Initially, we followed some naming convention from BKP, keeping the singular "beam". Luckily, we moved to more conventional "beams" upstream and luckily no device is using yet the SB timestamp variables, so we are good to rename them. --- core/environment/transition_startactivity.go | 4 ++-- core/integration/bookkeeping/plugin.go | 8 ++++---- core/integration/lhc/plugin.go | 12 ++++++------ docs/handbook/configuration.md | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/core/environment/transition_startactivity.go b/core/environment/transition_startactivity.go index 21c6ec9ec..8361bed21 100644 --- a/core/environment/transition_startactivity.go +++ b/core/environment/transition_startactivity.go @@ -85,8 +85,8 @@ func (t StartActivityTransition) do(env *Environment) (err error) { "fill_info_fill_number", "fill_info_filling_scheme", "fill_info_beam_type", - "fill_info_stable_beam_start_ms", - "fill_info_stable_beam_end_ms", + "fill_info_stable_beams_start_ms", + "fill_info_stable_beams_end_ms", "run_type", "run_start_time_ms", "run_end_time_ms", // included to ensure that a cleared SOEOR timestamp is propagated to all tasks during START-STOP-START diff --git a/core/integration/bookkeeping/plugin.go b/core/integration/bookkeeping/plugin.go index 476fdb1be..49344a7af 100644 --- a/core/integration/bookkeeping/plugin.go +++ b/core/integration/bookkeeping/plugin.go @@ -1446,10 +1446,10 @@ func (p *Plugin) CallStack(data interface{}) (stack map[string]interface{}) { parentRole.SetGlobalRuntimeVar("fill_info_filling_scheme", lhcInfo.FillingSchemeName) parentRole.SetGlobalRuntimeVar("fill_info_beam_type", lhcInfo.BeamType) if lhcInfo.StableBeamsStart != nil { - parentRole.SetGlobalRuntimeVar("fill_info_stable_beam_start_ms", strconv.FormatInt(*lhcInfo.StableBeamsStart, 10)) + parentRole.SetGlobalRuntimeVar("fill_info_stable_beams_start_ms", strconv.FormatInt(*lhcInfo.StableBeamsStart, 10)) } if lhcInfo.StableBeamsEnd != nil { - parentRole.SetGlobalRuntimeVar("fill_info_stable_beam_end_ms", strconv.FormatInt(*lhcInfo.StableBeamsEnd, 10)) + parentRole.SetGlobalRuntimeVar("fill_info_stable_beams_end_ms", strconv.FormatInt(*lhcInfo.StableBeamsEnd, 10)) } log.WithField("partition", envId). WithField("level", infologger.IL_Devel). @@ -1471,8 +1471,8 @@ func (p *Plugin) CallStack(data interface{}) (stack map[string]interface{}) { parentRole.DeleteGlobalRuntimeVar("fill_info_fill_number") parentRole.DeleteGlobalRuntimeVar("fill_info_filling_scheme") parentRole.DeleteGlobalRuntimeVar("fill_info_beam_type") - parentRole.DeleteGlobalRuntimeVar("fill_info_stable_beam_start_ms") - parentRole.DeleteGlobalRuntimeVar("fill_info_stable_beam_end_ms") + parentRole.DeleteGlobalRuntimeVar("fill_info_stable_beams_start_ms") + parentRole.DeleteGlobalRuntimeVar("fill_info_stable_beams_end_ms") } stack["RetrieveFillInfo"] = func() (out string) { diff --git a/core/integration/lhc/plugin.go b/core/integration/lhc/plugin.go index ed9f01e25..d29177c6a 100644 --- a/core/integration/lhc/plugin.go +++ b/core/integration/lhc/plugin.go @@ -307,8 +307,8 @@ func (p *Plugin) updateFillInfo(call *callable.Call) (out string) { parentRole.DeleteGlobalRuntimeVar("fill_info_fill_number") parentRole.DeleteGlobalRuntimeVar("fill_info_filling_scheme") parentRole.DeleteGlobalRuntimeVar("fill_info_beam_type") - parentRole.DeleteGlobalRuntimeVar("fill_info_stable_beam_start_ms") - parentRole.DeleteGlobalRuntimeVar("fill_info_stable_beam_end_ms") + parentRole.DeleteGlobalRuntimeVar("fill_info_stable_beams_start_ms") + parentRole.DeleteGlobalRuntimeVar("fill_info_stable_beams_end_ms") log.WithField(infologger.Level, infologger.IL_Devel). Debug("NO_BEAM — cleared fill info vars and set beam mode only") @@ -320,14 +320,14 @@ func (p *Plugin) updateFillInfo(call *callable.Call) (out string) { parentRole.SetGlobalRuntimeVar("fill_info_filling_scheme", state.FillingSchemeName) parentRole.SetGlobalRuntimeVar("fill_info_beam_type", state.BeamType) if state.StableBeamsStart > 0 { - parentRole.SetGlobalRuntimeVar("fill_info_stable_beam_start_ms", strconv.FormatInt(state.StableBeamsStart, 10)) + parentRole.SetGlobalRuntimeVar("fill_info_stable_beams_start_ms", strconv.FormatInt(state.StableBeamsStart, 10)) } else { - parentRole.DeleteGlobalRuntimeVar("fill_info_stable_beam_start_ms") + parentRole.DeleteGlobalRuntimeVar("fill_info_stable_beams_start_ms") } if state.StableBeamsEnd > 0 { - parentRole.SetGlobalRuntimeVar("fill_info_stable_beam_end_ms", strconv.FormatInt(state.StableBeamsEnd, 10)) + parentRole.SetGlobalRuntimeVar("fill_info_stable_beams_end_ms", strconv.FormatInt(state.StableBeamsEnd, 10)) } else { - parentRole.DeleteGlobalRuntimeVar("fill_info_stable_beam_end_ms") + parentRole.DeleteGlobalRuntimeVar("fill_info_stable_beams_end_ms") } log.WithField("fillNumber", state.FillNumber). diff --git a/docs/handbook/configuration.md b/docs/handbook/configuration.md index 637fb59a5..9cf18ee59 100644 --- a/docs/handbook/configuration.md +++ b/docs/handbook/configuration.md @@ -428,16 +428,16 @@ In addition to the above, which varies depending on the configuration of the env * `fill_info_fill_number` * `fill_info_filling_scheme` * `fill_info_beam_type` - * `fill_info_stable_beam_start_ms` - * `fill_info_stable_beam_end_ms` + * `fill_info_stable_beams_start_ms` + * `fill_info_stable_beams_end_ms` * `run_type` * `run_start_time_ms` * `lhc_period` * `fillInfoFillNumber` * `fillInfoFillingScheme` * `fillInfoBeamType` - * `fillInfoStableBeamStartMs` - * `fillInfoStableBeamEndMs` + * `fillInfoStableBeamsStartMs` + * `fillInfoStableBeamsEndMs` * `runType` * `runStartTimeMs` * `lhcPeriod` From 4ed69a71ed0548fc8016cacab750fc54df995b33 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Jun 2025 21:22:50 +0000 Subject: [PATCH 19/25] Bump github.com/cloudflare/circl from 1.3.7 to 1.6.1 Bumps [github.com/cloudflare/circl](https://github.com/cloudflare/circl) from 1.3.7 to 1.6.1. - [Release notes](https://github.com/cloudflare/circl/releases) - [Commits](https://github.com/cloudflare/circl/compare/v1.3.7...v1.6.1) --- updated-dependencies: - dependency-name: github.com/cloudflare/circl dependency-version: 1.6.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- go.mod | 9 ++------- go.sum | 32 +++----------------------------- 2 files changed, 5 insertions(+), 36 deletions(-) diff --git a/go.mod b/go.mod index 5cf831e29..3021f600c 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,6 @@ replace github.com/imdario/mergo => github.com/imdario/mergo v0.3.16 replace github.com/armon/go-metrics => github.com/hashicorp/go-metrics v0.5.3 require ( - github.com/AlecAivazis/survey/v2 v2.3.7 github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver v1.5.0 // indirect github.com/Masterminds/sprig v2.22.0+incompatible // indirect @@ -58,7 +57,6 @@ require ( github.com/spf13/viper v1.18.2 github.com/teo/logrus-prefixed-formatter v0.5.3-0.20230717095749-669d57324f0a github.com/valyala/fasttemplate v1.2.2 - github.com/xeipuuv/gojsonschema v1.2.0 github.com/xlab/treeprint v1.2.0 golang.org/x/crypto v0.36.0 golang.org/x/net v0.38.0 @@ -76,6 +74,7 @@ require ( github.com/gogo/protobuf v1.3.2 github.com/hashicorp/go-multierror v1.1.1 github.com/iancoleman/strcase v0.3.0 + github.com/influxdata/line-protocol/v2 v2.2.1 github.com/onsi/ginkgo/v2 v2.19.0 github.com/onsi/gomega v1.34.1 github.com/swaggo/http-swagger/v2 v2.0.2 @@ -89,7 +88,7 @@ require ( github.com/armon/go-metrics v0.5.3 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/cloudflare/circl v1.3.7 // indirect + github.com/cloudflare/circl v1.6.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect github.com/cyphar/filepath-securejoin v0.2.5 // indirect github.com/emirpasic/gods v1.18.1 // indirect @@ -118,11 +117,9 @@ require ( github.com/huandu/xstrings v1.4.0 // indirect github.com/imdario/mergo v0.3.4 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/influxdata/line-protocol/v2 v2.2.1 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 // indirect - github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/klauspost/compress v1.17.7 // indirect github.com/kylelemons/godebug v1.1.0 // indirect @@ -162,8 +159,6 @@ require ( github.com/urfave/cli/v2 v2.3.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect - github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect - github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/mod v0.23.0 // indirect golang.org/x/sync v0.12.0 // indirect diff --git a/go.sum b/go.sum index e63fcbbfc..88615a5d8 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,5 @@ dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= -github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ= -github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= @@ -15,8 +13,6 @@ github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuN github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s= -github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w= github.com/ProtonMail/go-crypto v1.1.3 h1:nRBOetoydLeUb4nHajyO2bKqMLfWQ/ZPwkXqXxPxCFk= github.com/ProtonMail/go-crypto v1.1.3/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -42,15 +38,13 @@ github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= -github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= -github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= +github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0= +github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI= -github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/cyphar/filepath-securejoin v0.2.5 h1:6iR5tXJ/e6tJZzzdMc1km3Sa7RRIVBKAK32O2s7AYfo= github.com/cyphar/filepath-securejoin v0.2.5/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -59,8 +53,6 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/denisbrodbeck/machineid v1.0.1 h1:geKr9qtkB876mXguW2X6TU4ZynleN6ezuMSRhl4D7AQ= github.com/denisbrodbeck/machineid v1.0.1/go.mod h1:dJUwb7PTidGDeYyUBmXZ2GphQBbjJCrnectwCyxcUSI= -github.com/dmarkham/enumer v1.5.8 h1:fIF11F9l5jyD++YYvxcSH5WgHfeaSGPaN/T4kOQ4qEM= -github.com/dmarkham/enumer v1.5.8/go.mod h1:d10o8R3t/gROm2p3BXqTkMt2+HMuxEmWCXzorAruYak= github.com/dmarkham/enumer v1.5.11 h1:quorLCaEfzjJ23Pf7PB9lyyaHseh91YfTM/sAD/4Mbo= github.com/dmarkham/enumer v1.5.11/go.mod h1:yixql+kDDQRYqcuBM2n9Vlt7NoT9ixgXhaXry8vmRg8= github.com/elazarl/goproxy v1.2.1 h1:njjgvO6cRG9rIqN2ebkqy6cQz2Njkx7Fsfv/zIZqgug= @@ -195,8 +187,6 @@ github.com/hashicorp/memberlist v0.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0= github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY= github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= -github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog= -github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68= github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= @@ -206,6 +196,7 @@ github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+h github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/influxdata/line-protocol-corpus v0.0.0-20210519164801-ca6fa5da0184/go.mod h1:03nmhxzZ7Xk2pdG+lmMd7mHDfeVOYFyhOgwO61qWU98= +github.com/influxdata/line-protocol-corpus v0.0.0-20210922080147-aa28ccfb8937 h1:MHJNQ+p99hFATQm6ORoLmpUCF7ovjwEFshs/NHzAbig= github.com/influxdata/line-protocol-corpus v0.0.0-20210922080147-aa28ccfb8937/go.mod h1:BKR9c0uHSmRgM/se9JhFHtTT7JTO67X23MtKMHtZcpo= github.com/influxdata/line-protocol/v2 v2.0.0-20210312151457-c52fdecb625a/go.mod h1:6+9Xt5Sq1rWx+glMgxhcg2c0DUaehK+5TDcPZ76GypY= github.com/influxdata/line-protocol/v2 v2.1.0/go.mod h1:QKw43hdUBg3GTk2iC3iyCxksNj7PX9aUSeYOYE/ceHY= @@ -224,8 +215,6 @@ github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 h1:uC1QfSlInpQ github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= github.com/k0kubun/pp v3.0.1+incompatible h1:3tqvf7QgUnZ5tXO6pNAZlrvHgl6DvifjDrd9g2S9Z40= github.com/k0kubun/pp v3.0.1+incompatible/go.mod h1:GWse8YhT0p8pT4ir3ZgBbfZild3tgzSScAn6HmfYukg= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= @@ -255,7 +244,6 @@ github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3v github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= @@ -276,7 +264,6 @@ github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mesos/mesos-go v0.0.11 h1:jMp9+W3zLu46g8EuP2su2Sjj7ipBh4N/g65c0kzGl/8= github.com/mesos/mesos-go v0.0.11/go.mod h1:kPYCMQ9gsOXVAle1OsoY4I1+9kPu8GHkf88aV59fDr4= -github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= @@ -416,7 +403,6 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= @@ -449,13 +435,6 @@ github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY= github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8= github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= -github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -479,8 +458,6 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= -golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -558,7 +535,6 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= @@ -573,8 +549,6 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= -golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 61479b7e9bddcad03e50e0b597a4fd5918352e00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Tich=C3=A1k?= Date: Fri, 21 Nov 2025 14:48:51 +0100 Subject: [PATCH 20/25] [monitoring] fixed cleaning of monitoring buffers after Stop --- common/monitoring/monitoring.go | 2 ++ common/monitoring/monitoring_test.go | 53 ++++++++++++++++++---------- 2 files changed, 36 insertions(+), 19 deletions(-) diff --git a/common/monitoring/monitoring.go b/common/monitoring/monitoring.go index f64339bdb..ed22df9da 100644 --- a/common/monitoring/monitoring.go +++ b/common/monitoring/monitoring.go @@ -172,6 +172,8 @@ func Stop() { if !ok { waitUntilRunningChannel = make(chan struct{}) } + metricsInternal.Clear() + metricsHistogramInternal.Clear() <-endChannel } diff --git a/common/monitoring/monitoring_test.go b/common/monitoring/monitoring_test.go index dd98cf6b8..2facaf146 100644 --- a/common/monitoring/monitoring_test.go +++ b/common/monitoring/monitoring_test.go @@ -79,17 +79,24 @@ func testFunction(t *testing.T, testToRun func(*testing.T)) { isRunningWithTimeout(t, time.Second) testToRun(t) Stop() + + if len(metricsInternal.GetMetrics()) != 0 { + t.Fatal("didn't clear metrics properly after tests") + } + if len(metricsHistogramInternal.GetMetrics()) != 0 { + t.Fatal("didn't clear histo metrics properly after tests") + } } func TestSendingSingleMetric(t *testing.T) { testFunction(t, func(t *testing.T) { - metric := &Metric{name: "test"} + metric := &Metric{name: "testsinglemetric"} Send(metric) hasNumberOfMetrics(t, time.Second, 1) aggregatedMetrics := metricsInternal.GetMetrics() - if aggregatedMetrics[0].name != "test" { + if aggregatedMetrics[0].name != "testsinglemetric" { t.Errorf("Got wrong name %s in stored metric", aggregatedMetrics[0].name) } }) @@ -97,7 +104,7 @@ func TestSendingSingleMetric(t *testing.T) { func TestExportingMetrics(t *testing.T) { testFunction(t, func(t *testing.T) { - metric := &Metric{name: "test"} + metric := &Metric{name: "testexporting"} Send(metric) hasNumberOfMetrics(t, time.Second, 1) @@ -105,28 +112,36 @@ func TestExportingMetrics(t *testing.T) { metricsToExport := <-metricsExportedToRequest if len(metricsToExport) != 1 { - t.Errorf("Got wrong amount of metrics %d, expected 1", len(metricsToExport)) + t.Fatalf("Got wrong amount of metrics %d, expected 1", len(metricsToExport)) } - if metricsToExport[0].name != "test" { - t.Errorf("Got wrong name of metric %s, expected test", metricsToExport[0].name) + if metricsToExport[0].name != "testexporting" { + t.Fatalf("Got wrong name of metric %s, expected testexporting", metricsToExport[0].name) } }) } func TestHttpRun(t *testing.T) { - go Run(9876, "/metrics") + port := uint16(9876) + endpoint := "/metrics" + go Run(port, endpoint) defer Stop() isRunningWithTimeout(t, 5*time.Second) - metric := Metric{name: "test"} - metric.timestamp = time.Unix(10, 0) - metric.AddTag("tag1", "42") - metric.SetFieldInt64("value1", 11) + sendAndTestMetric(t, port, endpoint, "testhttprun1", time.Unix(10, 0), "tag1", "42", "value1", 11) + sendAndTestMetric(t, port, endpoint, "testhttprun2", time.Unix(11, 0), "tag2", "43", "value2", 12) + sendAndTestMetric(t, port, endpoint, "testhttprun3", time.Unix(12, 0), "tag3", "44", "value3", 13) + sendAndTestMetric(t, port, endpoint, "testhttprun4", time.Unix(13, 0), "tag4", "45", "value4", 14) +} + +func sendAndTestMetric(t *testing.T, port uint16, endpoint string, metricName string, timestamp time.Time, tagName string, tagVal string, fieldName string, fieldVal int64) { + metric := Metric{name: metricName, timestamp: timestamp} + metric.AddTag(tagName, tagVal) + metric.SetFieldInt64(fieldName, fieldVal) Send(&metric) - response, err := http.Get("http://localhost:9876/metrics") + response, err := http.Get(fmt.Sprintf("http://localhost:%d%s", port, endpoint)) if err != nil { t.Fatalf("Failed to GET metrics at port 9876: %v", err) } @@ -142,19 +157,19 @@ func TestHttpRun(t *testing.T) { receivedMetric := receivedMetrics[0] - if receivedMetric.Name != "test" { - t.Errorf("Got wrong name of metric %s, expected test", receivedMetric.Name) + if receivedMetric.Name != metricName { + t.Errorf("Got wrong name of metric %s, expected %s", receivedMetric.Name, metricName) } - if receivedMetric.Timestamp != time.Unix(10, 0).UnixNano() { - t.Errorf("Got wrong timestamp of metric %d, expected 10", receivedMetric.Timestamp) + if receivedMetric.Timestamp != timestamp.UnixNano() { + t.Errorf("Got wrong timestamp of metric %d, expected %v", receivedMetric.Timestamp, timestamp.UnixNano()) } if len(receivedMetric.Tags) != 1 { t.Errorf("Got wrong number of tags %d, expected 1", len(receivedMetric.Tags)) } - if receivedMetric.Tags["tag1"] != "42" { + if receivedMetric.Tags[tagName] != tagVal { t.Errorf("Failed to retreive tags: tag1 with value 42, %+v", receivedMetric.Tags) } @@ -162,8 +177,8 @@ func TestHttpRun(t *testing.T) { t.Errorf("Got wrong number of values %d, expected 1", len(receivedMetric.Fields)) } - if receivedMetric.Fields["value1"] != "11i" { - t.Errorf("Failed to retreive tags: value1 with value 11: %+v", receivedMetric.Fields) + if receivedMetric.Fields[fieldName] != fmt.Sprintf("%di", fieldVal) { + t.Errorf("Failed to retreive tags: %s with value %d: %+v", fieldName, fieldVal, receivedMetric.Fields) } } From d0a4e706a9e62bddded93a230c2901982564cfc5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 21 Nov 2025 11:06:54 +0000 Subject: [PATCH 21/25] Bump golang.org/x/crypto from 0.36.0 to 0.45.0 Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.36.0 to 0.45.0. - [Commits](https://github.com/golang/crypto/compare/v0.36.0...v0.45.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-version: 0.45.0 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- go.mod | 16 ++++++++-------- go.sum | 32 ++++++++++++++++---------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/go.mod b/go.mod index 3021f600c..1fd24d1c8 100644 --- a/go.mod +++ b/go.mod @@ -58,9 +58,9 @@ require ( github.com/teo/logrus-prefixed-formatter v0.5.3-0.20230717095749-669d57324f0a github.com/valyala/fasttemplate v1.2.2 github.com/xlab/treeprint v1.2.0 - golang.org/x/crypto v0.36.0 - golang.org/x/net v0.38.0 - golang.org/x/sys v0.31.0 + golang.org/x/crypto v0.45.0 + golang.org/x/net v0.47.0 + golang.org/x/sys v0.38.0 google.golang.org/grpc v1.62.1 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 google.golang.org/protobuf v1.34.1 @@ -160,11 +160,11 @@ require ( github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/mod v0.23.0 // indirect - golang.org/x/sync v0.12.0 // indirect - golang.org/x/term v0.30.0 // indirect - golang.org/x/text v0.23.0 // indirect - golang.org/x/tools v0.30.0 // indirect + golang.org/x/mod v0.29.0 // indirect + golang.org/x/sync v0.18.0 // indirect + golang.org/x/term v0.37.0 // indirect + golang.org/x/text v0.31.0 // indirect + golang.org/x/tools v0.38.0 // indirect google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect diff --git a/go.sum b/go.sum index 88615a5d8..a23533be8 100644 --- a/go.sum +++ b/go.sum @@ -450,16 +450,16 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= -golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= +golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= -golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= +golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -474,8 +474,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= -golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= +golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -484,8 +484,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= -golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= +golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -519,16 +519,16 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= -golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= +golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= +golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -539,8 +539,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -549,8 +549,8 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= -golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= +golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= +golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From d9ccf544d4f98312b3429258b6096486ed43cec3 Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Thu, 20 Nov 2025 16:57:23 +0100 Subject: [PATCH 22/25] Standardize properties sent to AliECS- and ODC-controlled tasks We define a common list of parameter keys sent to AliECS- and ODC-controlled tasks and facilitate adding new ones. At the same time, we extend the lists to include some more fill information. --- core/environment/transition_startactivity.go | 31 ++++++++------- core/environment/transition_stopactivity.go | 22 ++++++++--- core/integration/odc/plugin.go | 40 +++++++------------- docs/handbook/configuration.md | 18 ++++----- 4 files changed, 57 insertions(+), 54 deletions(-) diff --git a/core/environment/transition_startactivity.go b/core/environment/transition_startactivity.go index 8361bed21..be7ec03c6 100644 --- a/core/environment/transition_startactivity.go +++ b/core/environment/transition_startactivity.go @@ -38,6 +38,22 @@ import ( "github.com/iancoleman/strcase" ) +var StartActivityParameterKeys = []string{ + "fill_info_fill_number", + "fill_info_filling_scheme", + "fill_info_beam_type", + "fill_info_stable_beams_start_ms", + "fill_info_stable_beams_end_ms", + "run_number", + "run_type", + "run_start_time_ms", + "run_end_time_ms", // included to ensure that a cleared SOEOR timestamp is propagated to all tasks during START-STOP-START + "lhc_period", + "pdp_beam_type", + "pdp_override_run_start_time", + "original_run_number", +} + func NewStartActivityTransition(taskman *task.Manager) Transition { return &StartActivityTransition{ baseTransition: baseTransition{ @@ -81,20 +97,7 @@ func (t StartActivityTransition) do(env *Environment) (err error) { // Get a handle to the consolidated var stack of the root role of the env's workflow if wf := env.Workflow(); wf != nil { if cvs, cvsErr := wf.ConsolidatedVarStack(); cvsErr == nil { - for _, key := range []string{ - "fill_info_fill_number", - "fill_info_filling_scheme", - "fill_info_beam_type", - "fill_info_stable_beams_start_ms", - "fill_info_stable_beams_end_ms", - "run_type", - "run_start_time_ms", - "run_end_time_ms", // included to ensure that a cleared SOEOR timestamp is propagated to all tasks during START-STOP-START - "lhc_period", - "pdp_beam_type", - "pdp_override_run_start_time", - "original_run_number", - } { + for _, key := range StartActivityParameterKeys { if value, ok := cvs[key]; ok { // we push the above parameters with both camelCase and snake_case identifiers for convenience args[strcase.ToLowerCamel(key)] = value diff --git a/core/environment/transition_stopactivity.go b/core/environment/transition_stopactivity.go index 1533c68fe..8653302e1 100644 --- a/core/environment/transition_stopactivity.go +++ b/core/environment/transition_stopactivity.go @@ -36,6 +36,15 @@ import ( "github.com/iancoleman/strcase" ) +var StopActivityParameterKeys = []string{ + "fill_info_fill_number", + "fill_info_filling_scheme", + "fill_info_beam_type", + "fill_info_stable_beams_start_ms", + "fill_info_stable_beams_end_ms", + "run_end_time_ms", +} + func NewStopActivityTransition(taskman *task.Manager) Transition { return &StopActivityTransition{ baseTransition: baseTransition{ @@ -64,11 +73,14 @@ func (t StopActivityTransition) do(env *Environment) (err error) { // Get a handle to the consolidated var stack of the root role of the env's workflow if wf := env.Workflow(); wf != nil { if cvs, cvsErr := wf.ConsolidatedVarStack(); cvsErr == nil { - - // Propagate run end time to all tasks - if value, ok := cvs["run_end_time_ms"]; ok { - args[strcase.ToLowerCamel("run_end_time_ms")] = value - args["run_end_time_ms"] = value + // in principle, only stable beams end should change among fill info vars in a typical scenario, + // but just in case of more creative uses, we push all of them again. + for _, key := range StopActivityParameterKeys { + if value, ok := cvs[key]; ok { + // we push the above parameters with both camelCase and snake_case identifiers for convenience + args[strcase.ToLowerCamel(key)] = value + args[key] = value + } } } } diff --git a/core/integration/odc/plugin.go b/core/integration/odc/plugin.go index 9311aa177..1a9a9d261 100644 --- a/core/integration/odc/plugin.go +++ b/core/integration/odc/plugin.go @@ -1439,19 +1439,12 @@ func (p *Plugin) CallStack(data interface{}) (stack map[string]interface{}) { WithField("call", "Start"). Warn("cannot acquire run number for ODC") } - originalRunNumber, _ := varStack["original_run_number"] cleanupCountS, ok := varStack["__fmq_cleanup_count"] if !ok { log.WithField("partition", envId). WithField("call", "Start"). Warn("cannot acquire FairMQ devices cleanup count for ODC") } - runStartTimeMs, ok := varStack["run_start_time_ms"] - if !ok { - log.WithField("partition", envId). - WithField("call", "Start"). - Warn("cannot acquire run_start_time_ms") - } var ( runNumberu64 uint64 @@ -1478,12 +1471,12 @@ func (p *Plugin) CallStack(data interface{}) (stack map[string]interface{}) { timeout := callable.AcquireTimeout(ODC_START_TIMEOUT, varStack, "Start", envId) arguments := make(map[string]string) - arguments["run_number"] = rn arguments["runNumber"] = rn - arguments["run_start_time_ms"] = runStartTimeMs arguments["cleanup"] = strconv.Itoa(cleanupCount) - if len(originalRunNumber) > 0 { - arguments["original_run_number"] = originalRunNumber + for _, key := range environment.StartActivityParameterKeys { + if value, ok := varStack[key]; ok { + arguments[key] = value + } } ctx, cancel := integration.NewContext(envId, varStack, timeout) @@ -1522,15 +1515,13 @@ func (p *Plugin) CallStack(data interface{}) (stack map[string]interface{}) { Error("cannot acquire run number for ODC EOR") runNumberu64 = 0 } - runEndTimeMs, ok := varStack["run_end_time_ms"] - if !ok { - log.WithField("partition", envId). - WithField("call", "Stop"). - Warn("cannot acquire run_end_time_ms") - } arguments := make(map[string]string) - arguments["run_end_time_ms"] = runEndTimeMs + for _, key := range environment.StopActivityParameterKeys { + if value, ok := varStack[key]; ok { + arguments[key] = value + } + } timeout := callable.AcquireTimeout(ODC_STOP_TIMEOUT, varStack, "Stop", envId) @@ -1594,15 +1585,12 @@ func (p *Plugin) CallStack(data interface{}) (stack map[string]interface{}) { Error("cannot acquire run number for ODC EOR") runNumberu64 = 0 } - runEndTimeMs, ok := varStack["run_end_time_ms"] - if !ok { - log.WithField("partition", envId). - WithField("call", "EnsureStop"). - Warn("cannot acquire run_end_time_ms") - } - arguments := make(map[string]string) - arguments["run_end_time_ms"] = runEndTimeMs + for _, key := range environment.StopActivityParameterKeys { + if value, ok := varStack[key]; ok { + arguments[key] = value + } + } err = handleStop(ctx, p.odcClient, arguments, paddingTimeout, envId, runNumberu64, call) if err != nil { diff --git a/docs/handbook/configuration.md b/docs/handbook/configuration.md index 9cf18ee59..6acb3370e 100644 --- a/docs/handbook/configuration.md +++ b/docs/handbook/configuration.md @@ -424,7 +424,7 @@ Depending on the specification in the task template (`command.env`, `command.arg In addition to the above, which varies depending on the configuration of the environment itself as well as on the configuration of the system as a whole, some special values are pushed by AliECS itself during `START_ACTIVITY`: - * `runNumber` + * `run_number` * `fill_info_fill_number` * `fill_info_filling_scheme` * `fill_info_beam_type` @@ -432,22 +432,22 @@ In addition to the above, which varies depending on the configuration of the env * `fill_info_stable_beams_end_ms` * `run_type` * `run_start_time_ms` + * `run_end_time_ms` (as an empty value) * `lhc_period` - * `fillInfoFillNumber` - * `fillInfoFillingScheme` - * `fillInfoBeamType` - * `fillInfoStableBeamsStartMs` - * `fillInfoStableBeamsEndMs` - * `runType` - * `runStartTimeMs` - * `lhcPeriod` * `pdp_beam_type` * `pdp_override_run_start_time` * `original_run_number` +For AliECS-controlled tasks, the same values are additionally pushed with keys in camelCase format. + The following values are pushed by AliECS during `STOP_ACTIVITY`: * `run_end_time_ms` + * `fill_info_fill_number` + * `fill_info_filling_scheme` + * `fill_info_beam_type` + * `fill_info_stable_beam_start_ms` + * `fill_info_stable_beam_end_ms` FairMQ task implementors should expect that these values are written to the FairMQ properties map right before the `RUN` and `STOP` transitions via `SetProperty` calls. From 01ab88e40ebaa808a77f006effa62bb723cb1576 Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Fri, 21 Nov 2025 10:59:27 +0100 Subject: [PATCH 23/25] Continue all remaining jobs in make check if one fails Given that our checks are rather lightweight, it's useful to avoid cancelling other jobs in the matrix if one fails. This way we can recognize if an issue is platform-specific or is intermittent. --- .github/workflows/control.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/control.yml b/.github/workflows/control.yml index 57de4f793..5ad85275a 100644 --- a/.github/workflows/control.yml +++ b/.github/workflows/control.yml @@ -11,6 +11,7 @@ jobs: name: Basic Make Check runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: os: [macOS-latest, ubuntu-24.04] go: [ '1.24.2' ] From 241a1b5e6cdd3881706a627824ab79ef99271866 Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Fri, 21 Nov 2025 11:21:53 +0100 Subject: [PATCH 24/25] Send the same properties upon run error as for heathly stop Closes OCTRL-1070. --- core/environment/transition_goerror.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/core/environment/transition_goerror.go b/core/environment/transition_goerror.go index 6b59d85f7..c8adb14e2 100644 --- a/core/environment/transition_goerror.go +++ b/core/environment/transition_goerror.go @@ -25,6 +25,7 @@ package environment import ( + "github.com/AliceO2Group/Control/core/controlcommands" "github.com/AliceO2Group/Control/core/task" "github.com/AliceO2Group/Control/core/task/sm" ) @@ -50,12 +51,21 @@ func (t GoErrorTransition) do(env *Environment) (err error) { return t.IsSafeToStop() }) if len(toStop) > 0 { + args := controlcommands.PropertyMap{} + if cvs, err := env.Workflow().ConsolidatedVarStack(); err == nil { + for _, key := range StopActivityParameterKeys { + if value, ok := cvs[key]; ok { + args[key] = value + } + } + } + taskmanMessage := task.NewTransitionTaskMessage( toStop, sm.RUNNING.String(), sm.STOP.String(), sm.CONFIGURED.String(), - nil, + args, env.Id(), ) t.taskman.MessageChannel <- taskmanMessage From adffc9fa562032998b2aea7eb699d77aa2fea976 Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Thu, 4 Dec 2025 10:47:07 +0100 Subject: [PATCH 25/25] Bump to v1.46.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 5b07e409f..fffb89137 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ # GNU Make syntax VERSION_MAJOR := 1 -VERSION_MINOR := 45 +VERSION_MINOR := 46 VERSION_PATCH := 0