From 0624733c0cbdb733544b01d29c59b3b67ec2a439 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Sat, 27 Dec 2025 13:53:01 +0800 Subject: [PATCH] platform: Add GetStartedAt for StartedService --- daemon/started_service.go | 9 ++ daemon/started_service.pb.go | 150 +++++++++++++++++--------- daemon/started_service.proto | 5 + daemon/started_service_grpc.pb.go | 39 +++++++ experimental/libbox/command_client.go | 13 +++ 5 files changed, 166 insertions(+), 50 deletions(-) diff --git a/daemon/started_service.go b/daemon/started_service.go index 65adac5d1..4f147cf81 100644 --- a/daemon/started_service.go +++ b/daemon/started_service.go @@ -50,6 +50,7 @@ type StartedService struct { logSubscriber *observable.Subscriber[*log.Entry] logObserver *observable.Observer[*log.Entry] instance *Instance + startedAt time.Time urlTestSubscriber *observable.Subscriber[struct{}] urlTestObserver *observable.Observer[struct{}] urlTestHistoryStorage *urltest.HistoryStorage @@ -193,6 +194,7 @@ func (s *StartedService) StartOrReloadService(profileContent string, options *Ov if err != nil { return s.updateStatusError(err) } + s.startedAt = time.Now() s.updateStatus(ServiceStatus_STARTED) s.serviceAccess.Unlock() runtime.GC() @@ -215,6 +217,7 @@ func (s *StartedService) CloseService() error { } } s.instance = nil + s.startedAt = time.Time{} s.updateStatus(ServiceStatus_IDLE) s.serviceAccess.Unlock() runtime.GC() @@ -803,6 +806,12 @@ func (s *StartedService) GetDeprecatedWarnings(ctx context.Context, empty *empty }, nil } +func (s *StartedService) GetStartedAt(ctx context.Context, empty *emptypb.Empty) (*StartedAt, error) { + s.serviceAccess.RLock() + defer s.serviceAccess.RUnlock() + return &StartedAt{StartedAt: s.startedAt.UnixMilli()}, nil +} + func (s *StartedService) SubscribeHelperEvents(empty *emptypb.Empty, server grpc.ServerStreamingServer[HelperRequest]) error { return os.ErrInvalid } diff --git a/daemon/started_service.pb.go b/daemon/started_service.pb.go index dcd94feb8..3a820e6f7 100644 --- a/daemon/started_service.pb.go +++ b/daemon/started_service.pb.go @@ -1567,6 +1567,50 @@ func (x *DeprecatedWarning) GetMigrationLink() string { return "" } +type StartedAt struct { + state protoimpl.MessageState `protogen:"open.v1"` + StartedAt int64 `protobuf:"varint,1,opt,name=startedAt,proto3" json:"startedAt,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *StartedAt) Reset() { + *x = StartedAt{} + mi := &file_daemon_started_service_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StartedAt) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StartedAt) ProtoMessage() {} + +func (x *StartedAt) ProtoReflect() protoreflect.Message { + mi := &file_daemon_started_service_proto_msgTypes[22] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StartedAt.ProtoReflect.Descriptor instead. +func (*StartedAt) Descriptor() ([]byte, []int) { + return file_daemon_started_service_proto_rawDescGZIP(), []int{22} +} + +func (x *StartedAt) GetStartedAt() int64 { + if x != nil { + return x.StartedAt + } + return 0 +} + type Log_Message struct { state protoimpl.MessageState `protogen:"open.v1"` Level LogLevel `protobuf:"varint,1,opt,name=level,proto3,enum=daemon.LogLevel" json:"level,omitempty"` @@ -1577,7 +1621,7 @@ type Log_Message struct { func (x *Log_Message) Reset() { *x = Log_Message{} - mi := &file_daemon_started_service_proto_msgTypes[22] + mi := &file_daemon_started_service_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1589,7 +1633,7 @@ func (x *Log_Message) String() string { func (*Log_Message) ProtoMessage() {} func (x *Log_Message) ProtoReflect() protoreflect.Message { - mi := &file_daemon_started_service_proto_msgTypes[22] + mi := &file_daemon_started_service_proto_msgTypes[23] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1728,7 +1772,9 @@ const file_daemon_started_service_proto_rawDesc = "" + "\x11DeprecatedWarning\x12\x18\n" + "\amessage\x18\x01 \x01(\tR\amessage\x12\x1c\n" + "\timpending\x18\x02 \x01(\bR\timpending\x12$\n" + - "\rmigrationLink\x18\x03 \x01(\tR\rmigrationLink*U\n" + + "\rmigrationLink\x18\x03 \x01(\tR\rmigrationLink\")\n" + + "\tStartedAt\x12\x1c\n" + + "\tstartedAt\x18\x01 \x01(\x03R\tstartedAt*U\n" + "\bLogLevel\x12\t\n" + "\x05PANIC\x10\x00\x12\t\n" + "\x05FATAL\x10\x01\x12\t\n" + @@ -1746,7 +1792,7 @@ const file_daemon_started_service_proto_rawDesc = "" + "\x10ConnectionSortBy\x12\b\n" + "\x04DATE\x10\x00\x12\v\n" + "\aTRAFFIC\x10\x01\x12\x11\n" + - "\rTOTAL_TRAFFIC\x10\x022\xb7\f\n" + + "\rTOTAL_TRAFFIC\x10\x022\xf4\f\n" + "\x0eStartedService\x12=\n" + "\vStopService\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12?\n" + "\rReloadService\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12K\n" + @@ -1767,7 +1813,8 @@ const file_daemon_started_service_proto_rawDesc = "" + "\x14SubscribeConnections\x12#.daemon.SubscribeConnectionsRequest\x1a\x13.daemon.Connections\"\x000\x01\x12K\n" + "\x0fCloseConnection\x12\x1e.daemon.CloseConnectionRequest\x1a\x16.google.protobuf.Empty\"\x00\x12G\n" + "\x13CloseAllConnections\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\"\x00\x12M\n" + - "\x15GetDeprecatedWarnings\x12\x16.google.protobuf.Empty\x1a\x1a.daemon.DeprecatedWarnings\"\x00\x12J\n" + + "\x15GetDeprecatedWarnings\x12\x16.google.protobuf.Empty\x1a\x1a.daemon.DeprecatedWarnings\"\x00\x12;\n" + + "\fGetStartedAt\x12\x16.google.protobuf.Empty\x1a\x11.daemon.StartedAt\"\x00\x12J\n" + "\x15SubscribeHelperEvents\x12\x16.google.protobuf.Empty\x1a\x15.daemon.HelperRequest\"\x000\x01\x12F\n" + "\x12SendHelperResponse\x12\x16.daemon.HelperResponse\x1a\x16.google.protobuf.Empty\"\x00B%Z#github.com/sagernet/sing-box/daemonb\x06proto3" @@ -1785,7 +1832,7 @@ func file_daemon_started_service_proto_rawDescGZIP() []byte { var ( file_daemon_started_service_proto_enumTypes = make([]protoimpl.EnumInfo, 4) - file_daemon_started_service_proto_msgTypes = make([]protoimpl.MessageInfo, 23) + file_daemon_started_service_proto_msgTypes = make([]protoimpl.MessageInfo, 24) file_daemon_started_service_proto_goTypes = []any{ (LogLevel)(0), // 0: daemon.LogLevel (ConnectionFilter)(0), // 1: daemon.ConnectionFilter @@ -1813,16 +1860,17 @@ var ( (*CloseConnectionRequest)(nil), // 23: daemon.CloseConnectionRequest (*DeprecatedWarnings)(nil), // 24: daemon.DeprecatedWarnings (*DeprecatedWarning)(nil), // 25: daemon.DeprecatedWarning - (*Log_Message)(nil), // 26: daemon.Log.Message - (*emptypb.Empty)(nil), // 27: google.protobuf.Empty - (*HelperResponse)(nil), // 28: daemon.HelperResponse - (*HelperRequest)(nil), // 29: daemon.HelperRequest + (*StartedAt)(nil), // 26: daemon.StartedAt + (*Log_Message)(nil), // 27: daemon.Log.Message + (*emptypb.Empty)(nil), // 28: google.protobuf.Empty + (*HelperResponse)(nil), // 29: daemon.HelperResponse + (*HelperRequest)(nil), // 30: daemon.HelperRequest } ) var file_daemon_started_service_proto_depIdxs = []int32{ 3, // 0: daemon.ServiceStatus.status:type_name -> daemon.ServiceStatus.Type - 26, // 1: daemon.Log.messages:type_name -> daemon.Log.Message + 27, // 1: daemon.Log.messages:type_name -> daemon.Log.Message 0, // 2: daemon.DefaultLogLevel.level:type_name -> daemon.LogLevel 11, // 3: daemon.Groups.group:type_name -> daemon.Group 12, // 4: daemon.Group.items:type_name -> daemon.GroupItem @@ -1831,52 +1879,54 @@ var file_daemon_started_service_proto_depIdxs = []int32{ 22, // 7: daemon.Connections.connections:type_name -> daemon.Connection 25, // 8: daemon.DeprecatedWarnings.warnings:type_name -> daemon.DeprecatedWarning 0, // 9: daemon.Log.Message.level:type_name -> daemon.LogLevel - 27, // 10: daemon.StartedService.StopService:input_type -> google.protobuf.Empty - 27, // 11: daemon.StartedService.ReloadService:input_type -> google.protobuf.Empty - 27, // 12: daemon.StartedService.SubscribeServiceStatus:input_type -> google.protobuf.Empty - 27, // 13: daemon.StartedService.SubscribeLog:input_type -> google.protobuf.Empty - 27, // 14: daemon.StartedService.GetDefaultLogLevel:input_type -> google.protobuf.Empty - 27, // 15: daemon.StartedService.ClearLogs:input_type -> google.protobuf.Empty + 28, // 10: daemon.StartedService.StopService:input_type -> google.protobuf.Empty + 28, // 11: daemon.StartedService.ReloadService:input_type -> google.protobuf.Empty + 28, // 12: daemon.StartedService.SubscribeServiceStatus:input_type -> google.protobuf.Empty + 28, // 13: daemon.StartedService.SubscribeLog:input_type -> google.protobuf.Empty + 28, // 14: daemon.StartedService.GetDefaultLogLevel:input_type -> google.protobuf.Empty + 28, // 15: daemon.StartedService.ClearLogs:input_type -> google.protobuf.Empty 6, // 16: daemon.StartedService.SubscribeStatus:input_type -> daemon.SubscribeStatusRequest - 27, // 17: daemon.StartedService.SubscribeGroups:input_type -> google.protobuf.Empty - 27, // 18: daemon.StartedService.GetClashModeStatus:input_type -> google.protobuf.Empty - 27, // 19: daemon.StartedService.SubscribeClashMode:input_type -> google.protobuf.Empty + 28, // 17: daemon.StartedService.SubscribeGroups:input_type -> google.protobuf.Empty + 28, // 18: daemon.StartedService.GetClashModeStatus:input_type -> google.protobuf.Empty + 28, // 19: daemon.StartedService.SubscribeClashMode:input_type -> google.protobuf.Empty 16, // 20: daemon.StartedService.SetClashMode:input_type -> daemon.ClashMode 13, // 21: daemon.StartedService.URLTest:input_type -> daemon.URLTestRequest 14, // 22: daemon.StartedService.SelectOutbound:input_type -> daemon.SelectOutboundRequest 15, // 23: daemon.StartedService.SetGroupExpand:input_type -> daemon.SetGroupExpandRequest - 27, // 24: daemon.StartedService.GetSystemProxyStatus:input_type -> google.protobuf.Empty + 28, // 24: daemon.StartedService.GetSystemProxyStatus:input_type -> google.protobuf.Empty 19, // 25: daemon.StartedService.SetSystemProxyEnabled:input_type -> daemon.SetSystemProxyEnabledRequest 20, // 26: daemon.StartedService.SubscribeConnections:input_type -> daemon.SubscribeConnectionsRequest 23, // 27: daemon.StartedService.CloseConnection:input_type -> daemon.CloseConnectionRequest - 27, // 28: daemon.StartedService.CloseAllConnections:input_type -> google.protobuf.Empty - 27, // 29: daemon.StartedService.GetDeprecatedWarnings:input_type -> google.protobuf.Empty - 27, // 30: daemon.StartedService.SubscribeHelperEvents:input_type -> google.protobuf.Empty - 28, // 31: daemon.StartedService.SendHelperResponse:input_type -> daemon.HelperResponse - 27, // 32: daemon.StartedService.StopService:output_type -> google.protobuf.Empty - 27, // 33: daemon.StartedService.ReloadService:output_type -> google.protobuf.Empty - 4, // 34: daemon.StartedService.SubscribeServiceStatus:output_type -> daemon.ServiceStatus - 7, // 35: daemon.StartedService.SubscribeLog:output_type -> daemon.Log - 8, // 36: daemon.StartedService.GetDefaultLogLevel:output_type -> daemon.DefaultLogLevel - 27, // 37: daemon.StartedService.ClearLogs:output_type -> google.protobuf.Empty - 9, // 38: daemon.StartedService.SubscribeStatus:output_type -> daemon.Status - 10, // 39: daemon.StartedService.SubscribeGroups:output_type -> daemon.Groups - 17, // 40: daemon.StartedService.GetClashModeStatus:output_type -> daemon.ClashModeStatus - 16, // 41: daemon.StartedService.SubscribeClashMode:output_type -> daemon.ClashMode - 27, // 42: daemon.StartedService.SetClashMode:output_type -> google.protobuf.Empty - 27, // 43: daemon.StartedService.URLTest:output_type -> google.protobuf.Empty - 27, // 44: daemon.StartedService.SelectOutbound:output_type -> google.protobuf.Empty - 27, // 45: daemon.StartedService.SetGroupExpand:output_type -> google.protobuf.Empty - 18, // 46: daemon.StartedService.GetSystemProxyStatus:output_type -> daemon.SystemProxyStatus - 27, // 47: daemon.StartedService.SetSystemProxyEnabled:output_type -> google.protobuf.Empty - 21, // 48: daemon.StartedService.SubscribeConnections:output_type -> daemon.Connections - 27, // 49: daemon.StartedService.CloseConnection:output_type -> google.protobuf.Empty - 27, // 50: daemon.StartedService.CloseAllConnections:output_type -> google.protobuf.Empty - 24, // 51: daemon.StartedService.GetDeprecatedWarnings:output_type -> daemon.DeprecatedWarnings - 29, // 52: daemon.StartedService.SubscribeHelperEvents:output_type -> daemon.HelperRequest - 27, // 53: daemon.StartedService.SendHelperResponse:output_type -> google.protobuf.Empty - 32, // [32:54] is the sub-list for method output_type - 10, // [10:32] is the sub-list for method input_type + 28, // 28: daemon.StartedService.CloseAllConnections:input_type -> google.protobuf.Empty + 28, // 29: daemon.StartedService.GetDeprecatedWarnings:input_type -> google.protobuf.Empty + 28, // 30: daemon.StartedService.GetStartedAt:input_type -> google.protobuf.Empty + 28, // 31: daemon.StartedService.SubscribeHelperEvents:input_type -> google.protobuf.Empty + 29, // 32: daemon.StartedService.SendHelperResponse:input_type -> daemon.HelperResponse + 28, // 33: daemon.StartedService.StopService:output_type -> google.protobuf.Empty + 28, // 34: daemon.StartedService.ReloadService:output_type -> google.protobuf.Empty + 4, // 35: daemon.StartedService.SubscribeServiceStatus:output_type -> daemon.ServiceStatus + 7, // 36: daemon.StartedService.SubscribeLog:output_type -> daemon.Log + 8, // 37: daemon.StartedService.GetDefaultLogLevel:output_type -> daemon.DefaultLogLevel + 28, // 38: daemon.StartedService.ClearLogs:output_type -> google.protobuf.Empty + 9, // 39: daemon.StartedService.SubscribeStatus:output_type -> daemon.Status + 10, // 40: daemon.StartedService.SubscribeGroups:output_type -> daemon.Groups + 17, // 41: daemon.StartedService.GetClashModeStatus:output_type -> daemon.ClashModeStatus + 16, // 42: daemon.StartedService.SubscribeClashMode:output_type -> daemon.ClashMode + 28, // 43: daemon.StartedService.SetClashMode:output_type -> google.protobuf.Empty + 28, // 44: daemon.StartedService.URLTest:output_type -> google.protobuf.Empty + 28, // 45: daemon.StartedService.SelectOutbound:output_type -> google.protobuf.Empty + 28, // 46: daemon.StartedService.SetGroupExpand:output_type -> google.protobuf.Empty + 18, // 47: daemon.StartedService.GetSystemProxyStatus:output_type -> daemon.SystemProxyStatus + 28, // 48: daemon.StartedService.SetSystemProxyEnabled:output_type -> google.protobuf.Empty + 21, // 49: daemon.StartedService.SubscribeConnections:output_type -> daemon.Connections + 28, // 50: daemon.StartedService.CloseConnection:output_type -> google.protobuf.Empty + 28, // 51: daemon.StartedService.CloseAllConnections:output_type -> google.protobuf.Empty + 24, // 52: daemon.StartedService.GetDeprecatedWarnings:output_type -> daemon.DeprecatedWarnings + 26, // 53: daemon.StartedService.GetStartedAt:output_type -> daemon.StartedAt + 30, // 54: daemon.StartedService.SubscribeHelperEvents:output_type -> daemon.HelperRequest + 28, // 55: daemon.StartedService.SendHelperResponse:output_type -> google.protobuf.Empty + 33, // [33:56] is the sub-list for method output_type + 10, // [10:33] is the sub-list for method input_type 10, // [10:10] is the sub-list for extension type_name 10, // [10:10] is the sub-list for extension extendee 0, // [0:10] is the sub-list for field type_name @@ -1894,7 +1944,7 @@ func file_daemon_started_service_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_daemon_started_service_proto_rawDesc), len(file_daemon_started_service_proto_rawDesc)), NumEnums: 4, - NumMessages: 23, + NumMessages: 24, NumExtensions: 0, NumServices: 1, }, diff --git a/daemon/started_service.proto b/daemon/started_service.proto index 83b72ff85..b44e26135 100644 --- a/daemon/started_service.proto +++ b/daemon/started_service.proto @@ -32,6 +32,7 @@ service StartedService { rpc CloseConnection(CloseConnectionRequest) returns(google.protobuf.Empty) {} rpc CloseAllConnections(google.protobuf.Empty) returns(google.protobuf.Empty) {} rpc GetDeprecatedWarnings(google.protobuf.Empty) returns(DeprecatedWarnings) {} + rpc GetStartedAt(google.protobuf.Empty) returns(StartedAt) {} rpc SubscribeHelperEvents(google.protobuf.Empty) returns(stream HelperRequest) {} rpc SendHelperResponse(HelperResponse) returns(google.protobuf.Empty) {} @@ -202,4 +203,8 @@ message DeprecatedWarning { string message = 1; bool impending = 2; string migrationLink = 3; +} + +message StartedAt { + int64 startedAt = 1; } \ No newline at end of file diff --git a/daemon/started_service_grpc.pb.go b/daemon/started_service_grpc.pb.go index dec45dae6..a95804691 100644 --- a/daemon/started_service_grpc.pb.go +++ b/daemon/started_service_grpc.pb.go @@ -35,6 +35,7 @@ const ( StartedService_CloseConnection_FullMethodName = "/daemon.StartedService/CloseConnection" StartedService_CloseAllConnections_FullMethodName = "/daemon.StartedService/CloseAllConnections" StartedService_GetDeprecatedWarnings_FullMethodName = "/daemon.StartedService/GetDeprecatedWarnings" + StartedService_GetStartedAt_FullMethodName = "/daemon.StartedService/GetStartedAt" StartedService_SubscribeHelperEvents_FullMethodName = "/daemon.StartedService/SubscribeHelperEvents" StartedService_SendHelperResponse_FullMethodName = "/daemon.StartedService/SendHelperResponse" ) @@ -63,6 +64,7 @@ type StartedServiceClient interface { CloseConnection(ctx context.Context, in *CloseConnectionRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) CloseAllConnections(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) GetDeprecatedWarnings(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*DeprecatedWarnings, error) + GetStartedAt(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*StartedAt, error) SubscribeHelperEvents(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (grpc.ServerStreamingClient[HelperRequest], error) SendHelperResponse(ctx context.Context, in *HelperResponse, opts ...grpc.CallOption) (*emptypb.Empty, error) } @@ -329,6 +331,16 @@ func (c *startedServiceClient) GetDeprecatedWarnings(ctx context.Context, in *em return out, nil } +func (c *startedServiceClient) GetStartedAt(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*StartedAt, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(StartedAt) + err := c.cc.Invoke(ctx, StartedService_GetStartedAt_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *startedServiceClient) SubscribeHelperEvents(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (grpc.ServerStreamingClient[HelperRequest], error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) stream, err := c.cc.NewStream(ctx, &StartedService_ServiceDesc.Streams[6], StartedService_SubscribeHelperEvents_FullMethodName, cOpts...) @@ -382,6 +394,7 @@ type StartedServiceServer interface { CloseConnection(context.Context, *CloseConnectionRequest) (*emptypb.Empty, error) CloseAllConnections(context.Context, *emptypb.Empty) (*emptypb.Empty, error) GetDeprecatedWarnings(context.Context, *emptypb.Empty) (*DeprecatedWarnings, error) + GetStartedAt(context.Context, *emptypb.Empty) (*StartedAt, error) SubscribeHelperEvents(*emptypb.Empty, grpc.ServerStreamingServer[HelperRequest]) error SendHelperResponse(context.Context, *HelperResponse) (*emptypb.Empty, error) mustEmbedUnimplementedStartedServiceServer() @@ -474,6 +487,10 @@ func (UnimplementedStartedServiceServer) GetDeprecatedWarnings(context.Context, return nil, status.Errorf(codes.Unimplemented, "method GetDeprecatedWarnings not implemented") } +func (UnimplementedStartedServiceServer) GetStartedAt(context.Context, *emptypb.Empty) (*StartedAt, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetStartedAt not implemented") +} + func (UnimplementedStartedServiceServer) SubscribeHelperEvents(*emptypb.Empty, grpc.ServerStreamingServer[HelperRequest]) error { return status.Errorf(codes.Unimplemented, "method SubscribeHelperEvents not implemented") } @@ -820,6 +837,24 @@ func _StartedService_GetDeprecatedWarnings_Handler(srv interface{}, ctx context. return interceptor(ctx, in, info, handler) } +func _StartedService_GetStartedAt_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(emptypb.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(StartedServiceServer).GetStartedAt(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: StartedService_GetStartedAt_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StartedServiceServer).GetStartedAt(ctx, req.(*emptypb.Empty)) + } + return interceptor(ctx, in, info, handler) +} + func _StartedService_SubscribeHelperEvents_Handler(srv interface{}, stream grpc.ServerStream) error { m := new(emptypb.Empty) if err := stream.RecvMsg(m); err != nil { @@ -912,6 +947,10 @@ var StartedService_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetDeprecatedWarnings", Handler: _StartedService_GetDeprecatedWarnings_Handler, }, + { + MethodName: "GetStartedAt", + Handler: _StartedService_GetStartedAt_Handler, + }, { MethodName: "SendHelperResponse", Handler: _StartedService_SendHelperResponse_Handler, diff --git a/experimental/libbox/command_client.go b/experimental/libbox/command_client.go index 9885af6e2..8b60332ec 100644 --- a/experimental/libbox/command_client.go +++ b/experimental/libbox/command_client.go @@ -466,6 +466,19 @@ func (c *CommandClient) GetDeprecatedNotes() (DeprecatedNoteIterator, error) { return newIterator(notes), nil } +func (c *CommandClient) GetStartedAt() (int64, error) { + client, err := c.getClientForCall() + if err != nil { + return 0, err + } + + startedAt, err := client.GetStartedAt(context.Background(), &emptypb.Empty{}) + if err != nil { + return 0, err + } + return startedAt.StartedAt, nil +} + func (c *CommandClient) SetGroupExpand(groupTag string, isExpand bool) error { client, err := c.getClientForCall() if err != nil {