diff --git a/.changeset/agent-dispatch-queue-api.md b/.changeset/agent-dispatch-queue-api.md new file mode 100644 index 000000000..91ae5e25e --- /dev/null +++ b/.changeset/agent-dispatch-queue-api.md @@ -0,0 +1,6 @@ +--- +"github.com/livekit/protocol": patch +"@livekit/protocol": patch +--- + +Add the `AgentDispatchQueue` service with `QueuedJob` / `QueuedJobInput` / `QueuedJobStatus`, job group messages, `DispatchQueueConfig` / `DispatchLimit` / `DispatchLimitScope`, and an `AgentGrant.DispatchAdmin` grant diff --git a/auth/grants.go b/auth/grants.go index 4fe7c57f5..552c06763 100644 --- a/auth/grants.go +++ b/auth/grants.go @@ -583,6 +583,8 @@ type AgentGrant struct { SimulationAdmin bool `json:"simulationAdmin,omitempty"` // DatabaseAdmin grants access to a project's agent databases (AgentDB). DatabaseAdmin bool `json:"databaseAdmin,omitempty"` + // DispatchAdmin grants access to manage the project's outbound agent dispatch queue. + DispatchAdmin bool `json:"dispatchAdmin,omitempty"` } func (s *AgentGrant) Clone() *AgentGrant { @@ -603,6 +605,7 @@ func (s *AgentGrant) MarshalLogObject(e zapcore.ObjectEncoder) error { e.AddBool("Admin", s.Admin) e.AddBool("SimulationAdmin", s.SimulationAdmin) e.AddBool("DatabaseAdmin", s.DatabaseAdmin) + e.AddBool("DispatchAdmin", s.DispatchAdmin) return nil } diff --git a/auth/grants_test.go b/auth/grants_test.go index 211bc2097..042013088 100644 --- a/auth/grants_test.go +++ b/auth/grants_test.go @@ -120,7 +120,8 @@ func TestGrants(t *testing.T) { t.Run("clone with Agent", func(t *testing.T) { agent := &AgentGrant{ - Admin: true, + Admin: true, + DispatchAdmin: true, } grants := &ClaimGrants{ Identity: "identity", diff --git a/livekit/livekit_agent_dispatch_queue.pb.go b/livekit/livekit_agent_dispatch_queue.pb.go new file mode 100644 index 000000000..ddb1c46aa --- /dev/null +++ b/livekit/livekit_agent_dispatch_queue.pb.go @@ -0,0 +1,2118 @@ +// Copyright 2026 LiveKit, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.12 +// protoc v7.35.1 +// source: livekit_agent_dispatch_queue.proto + +package livekit + +import ( + _ "github.com/livekit/protocol/livekit/logger" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type QueuedJobStatus int32 + +const ( + QueuedJobStatus_QUEUED_JOB_STATUS_UNSPECIFIED QueuedJobStatus = 0 + // Awaiting capacity, or waiting on start_after. + QueuedJobStatus_QUEUED_JOB_STATUS_QUEUED QueuedJobStatus = 1 + // Admitted; CreateDispatch in flight. + QueuedJobStatus_QUEUED_JOB_STATUS_DISPATCHING QueuedJobStatus = 2 + // Dispatch created, agent job live. + QueuedJobStatus_QUEUED_JOB_STATUS_RUNNING QueuedJobStatus = 3 + QueuedJobStatus_QUEUED_JOB_STATUS_SUCCEEDED QueuedJobStatus = 4 + QueuedJobStatus_QUEUED_JOB_STATUS_FAILED QueuedJobStatus = 5 + // Removed, or cancelled with its group, before it was admitted. + QueuedJobStatus_QUEUED_JOB_STATUS_CANCELLED QueuedJobStatus = 6 + // Still queued at expires_at; never dispatched. Includes a job whose + // start_after never arrived before it expired. + QueuedJobStatus_QUEUED_JOB_STATUS_EXPIRED QueuedJobStatus = 7 +) + +// Enum value maps for QueuedJobStatus. +var ( + QueuedJobStatus_name = map[int32]string{ + 0: "QUEUED_JOB_STATUS_UNSPECIFIED", + 1: "QUEUED_JOB_STATUS_QUEUED", + 2: "QUEUED_JOB_STATUS_DISPATCHING", + 3: "QUEUED_JOB_STATUS_RUNNING", + 4: "QUEUED_JOB_STATUS_SUCCEEDED", + 5: "QUEUED_JOB_STATUS_FAILED", + 6: "QUEUED_JOB_STATUS_CANCELLED", + 7: "QUEUED_JOB_STATUS_EXPIRED", + } + QueuedJobStatus_value = map[string]int32{ + "QUEUED_JOB_STATUS_UNSPECIFIED": 0, + "QUEUED_JOB_STATUS_QUEUED": 1, + "QUEUED_JOB_STATUS_DISPATCHING": 2, + "QUEUED_JOB_STATUS_RUNNING": 3, + "QUEUED_JOB_STATUS_SUCCEEDED": 4, + "QUEUED_JOB_STATUS_FAILED": 5, + "QUEUED_JOB_STATUS_CANCELLED": 6, + "QUEUED_JOB_STATUS_EXPIRED": 7, + } +) + +func (x QueuedJobStatus) Enum() *QueuedJobStatus { + p := new(QueuedJobStatus) + *p = x + return p +} + +func (x QueuedJobStatus) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (QueuedJobStatus) Descriptor() protoreflect.EnumDescriptor { + return file_livekit_agent_dispatch_queue_proto_enumTypes[0].Descriptor() +} + +func (QueuedJobStatus) Type() protoreflect.EnumType { + return &file_livekit_agent_dispatch_queue_proto_enumTypes[0] +} + +func (x QueuedJobStatus) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use QueuedJobStatus.Descriptor instead. +func (QueuedJobStatus) EnumDescriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{0} +} + +// Which slice of the project's queued traffic a DispatchLimit applies to. +type DispatchLimitScope int32 + +const ( + // The project's whole queue. + DispatchLimitScope_DISPATCH_LIMIT_SCOPE_UNSPECIFIED DispatchLimitScope = 0 + // QueuedJobInput.agent_name. + DispatchLimitScope_DISPATCH_LIMIT_SCOPE_AGENT DispatchLimitScope = 1 +) + +// Enum value maps for DispatchLimitScope. +var ( + DispatchLimitScope_name = map[int32]string{ + 0: "DISPATCH_LIMIT_SCOPE_UNSPECIFIED", + 1: "DISPATCH_LIMIT_SCOPE_AGENT", + } + DispatchLimitScope_value = map[string]int32{ + "DISPATCH_LIMIT_SCOPE_UNSPECIFIED": 0, + "DISPATCH_LIMIT_SCOPE_AGENT": 1, + } +) + +func (x DispatchLimitScope) Enum() *DispatchLimitScope { + p := new(DispatchLimitScope) + *p = x + return p +} + +func (x DispatchLimitScope) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (DispatchLimitScope) Descriptor() protoreflect.EnumDescriptor { + return file_livekit_agent_dispatch_queue_proto_enumTypes[1].Descriptor() +} + +func (DispatchLimitScope) Type() protoreflect.EnumType { + return &file_livekit_agent_dispatch_queue_proto_enumTypes[1] +} + +func (x DispatchLimitScope) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use DispatchLimitScope.Descriptor instead. +func (DispatchLimitScope) EnumDescriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{1} +} + +// What to dispatch. Mirrors CreateAgentDispatchRequest so that a queued job and +// an immediate dispatch describe the same work. +type QueuedJobInput struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Must match the agent_name registered by the agent server. + AgentName string `protobuf:"bytes,1,opt,name=agent_name,json=agentName,proto3" json:"agent_name,omitempty"` + // Required. The queue does not invent room names; a caller wanting one room + // per job supplies its own unique name. + RoomName string `protobuf:"bytes,2,opt,name=room_name,json=roomName,proto3" json:"room_name,omitempty"` + // Required, unique per project. Re-adding with the same key returns the + // existing job rather than dispatching twice. + IdempotencyKey string `protobuf:"bytes,3,opt,name=idempotency_key,json=idempotencyKey,proto3" json:"idempotency_key,omitempty"` + Metadata string `protobuf:"bytes,4,opt,name=metadata,proto3" json:"metadata,omitempty"` + Attributes map[string]string `protobuf:"bytes,5,rep,name=attributes,proto3" json:"attributes,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Deployment string `protobuf:"bytes,6,opt,name=deployment,proto3" json:"deployment,omitempty"` + RestartPolicy JobRestartPolicy `protobuf:"varint,7,opt,name=restart_policy,json=restartPolicy,proto3,enum=livekit.JobRestartPolicy" json:"restart_policy,omitempty"` + // Never dispatch after this time; the job goes to EXPIRED instead. Capped at + // 8 days out to stay inside the row retention window, which also bounds + // start_after. + ExpiresAt *timestamppb.Timestamp `protobuf:"bytes,8,opt,name=expires_at,json=expiresAt,proto3,oneof" json:"expires_at,omitempty"` + // Per-job callbacks, signed with the project key, as with Egress per-request + // webhooks. Project-level webhooks fire regardless. + Webhooks []*WebhookConfig `protobuf:"bytes,9,rep,name=webhooks,proto3" json:"webhooks,omitempty"` + // Hold the job until this time. A floor, not an appointment: the job still + // waits on capacity once eligible, and eligibility only filters the FIFO + // scan - order stays created_at, so a held job keeps its original place in + // line. Must be before expires_at. + StartAfter *timestamppb.Timestamp `protobuf:"bytes,11,opt,name=start_after,json=startAfter,proto3,oneof" json:"start_after,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *QueuedJobInput) Reset() { + *x = QueuedJobInput{} + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *QueuedJobInput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueuedJobInput) ProtoMessage() {} + +func (x *QueuedJobInput) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[0] + 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 QueuedJobInput.ProtoReflect.Descriptor instead. +func (*QueuedJobInput) Descriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{0} +} + +func (x *QueuedJobInput) GetAgentName() string { + if x != nil { + return x.AgentName + } + return "" +} + +func (x *QueuedJobInput) GetRoomName() string { + if x != nil { + return x.RoomName + } + return "" +} + +func (x *QueuedJobInput) GetIdempotencyKey() string { + if x != nil { + return x.IdempotencyKey + } + return "" +} + +func (x *QueuedJobInput) GetMetadata() string { + if x != nil { + return x.Metadata + } + return "" +} + +func (x *QueuedJobInput) GetAttributes() map[string]string { + if x != nil { + return x.Attributes + } + return nil +} + +func (x *QueuedJobInput) GetDeployment() string { + if x != nil { + return x.Deployment + } + return "" +} + +func (x *QueuedJobInput) GetRestartPolicy() JobRestartPolicy { + if x != nil { + return x.RestartPolicy + } + return JobRestartPolicy_JRP_ON_FAILURE +} + +func (x *QueuedJobInput) GetExpiresAt() *timestamppb.Timestamp { + if x != nil { + return x.ExpiresAt + } + return nil +} + +func (x *QueuedJobInput) GetWebhooks() []*WebhookConfig { + if x != nil { + return x.Webhooks + } + return nil +} + +func (x *QueuedJobInput) GetStartAfter() *timestamppb.Timestamp { + if x != nil { + return x.StartAfter + } + return nil +} + +type QueuedJob struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + GroupId *string `protobuf:"bytes,2,opt,name=group_id,json=groupId,proto3,oneof" json:"group_id,omitempty"` + Status QueuedJobStatus `protobuf:"varint,3,opt,name=status,proto3,enum=livekit.QueuedJobStatus" json:"status,omitempty"` + Input *QueuedJobInput `protobuf:"bytes,4,opt,name=input,proto3" json:"input,omitempty"` + // Set once dispatch is invoked; the join point into the dispatch APIs. + DispatchId string `protobuf:"bytes,5,opt,name=dispatch_id,json=dispatchId,proto3" json:"dispatch_id,omitempty"` + // Set once the room is created. + RoomId string `protobuf:"bytes,6,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + // JSON the agent writes back before exiting; opaque to the queue and carried + // on the terminal webhook. + Result string `protobuf:"bytes,7,opt,name=result,proto3" json:"result,omitempty"` + // Set on FAILED, including exhaustion of infra retries. + Error string `protobuf:"bytes,8,opt,name=error,proto3" json:"error,omitempty"` + // Dispatch attempts made by the queue. Counts infra-level retries before a + // dispatch succeeds, not agent-side failures. + Attempts int32 `protobuf:"varint,9,opt,name=attempts,proto3" json:"attempts,omitempty"` + CreatedAt *timestamppb.Timestamp `protobuf:"bytes,10,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + DispatchedAt *timestamppb.Timestamp `protobuf:"bytes,11,opt,name=dispatched_at,json=dispatchedAt,proto3" json:"dispatched_at,omitempty"` + CompletedAt *timestamppb.Timestamp `protobuf:"bytes,12,opt,name=completed_at,json=completedAt,proto3" json:"completed_at,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *QueuedJob) Reset() { + *x = QueuedJob{} + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *QueuedJob) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueuedJob) ProtoMessage() {} + +func (x *QueuedJob) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[1] + 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 QueuedJob.ProtoReflect.Descriptor instead. +func (*QueuedJob) Descriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{1} +} + +func (x *QueuedJob) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *QueuedJob) GetGroupId() string { + if x != nil && x.GroupId != nil { + return *x.GroupId + } + return "" +} + +func (x *QueuedJob) GetStatus() QueuedJobStatus { + if x != nil { + return x.Status + } + return QueuedJobStatus_QUEUED_JOB_STATUS_UNSPECIFIED +} + +func (x *QueuedJob) GetInput() *QueuedJobInput { + if x != nil { + return x.Input + } + return nil +} + +func (x *QueuedJob) GetDispatchId() string { + if x != nil { + return x.DispatchId + } + return "" +} + +func (x *QueuedJob) GetRoomId() string { + if x != nil { + return x.RoomId + } + return "" +} + +func (x *QueuedJob) GetResult() string { + if x != nil { + return x.Result + } + return "" +} + +func (x *QueuedJob) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +func (x *QueuedJob) GetAttempts() int32 { + if x != nil { + return x.Attempts + } + return 0 +} + +func (x *QueuedJob) GetCreatedAt() *timestamppb.Timestamp { + if x != nil { + return x.CreatedAt + } + return nil +} + +func (x *QueuedJob) GetDispatchedAt() *timestamppb.Timestamp { + if x != nil { + return x.DispatchedAt + } + return nil +} + +func (x *QueuedJob) GetCompletedAt() *timestamppb.Timestamp { + if x != nil { + return x.CompletedAt + } + return nil +} + +type JobGroup struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // A paused group admits nothing; jobs already in flight run to completion. + Paused bool `protobuf:"varint,2,opt,name=paused,proto3" json:"paused,omitempty"` + CreatedAt *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + Counts []*JobGroup_StatusCount `protobuf:"bytes,4,rep,name=counts,proto3" json:"counts,omitempty"` + // Jobs from this group running at once, as set when the group was created. + // Zero means the dispatcher default applies. + ConcurrencyLimit uint32 `protobuf:"varint,5,opt,name=concurrency_limit,json=concurrencyLimit,proto3" json:"concurrency_limit,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *JobGroup) Reset() { + *x = JobGroup{} + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *JobGroup) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*JobGroup) ProtoMessage() {} + +func (x *JobGroup) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[2] + 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 JobGroup.ProtoReflect.Descriptor instead. +func (*JobGroup) Descriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{2} +} + +func (x *JobGroup) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *JobGroup) GetPaused() bool { + if x != nil { + return x.Paused + } + return false +} + +func (x *JobGroup) GetCreatedAt() *timestamppb.Timestamp { + if x != nil { + return x.CreatedAt + } + return nil +} + +func (x *JobGroup) GetCounts() []*JobGroup_StatusCount { + if x != nil { + return x.Counts + } + return nil +} + +func (x *JobGroup) GetConcurrencyLimit() uint32 { + if x != nil { + return x.ConcurrencyLimit + } + return 0 +} + +// One limit over a slice of the project's queued traffic. A job is evaluated +// against every limit it matches and the smallest remaining budget wins. +// Per-group limits are set on the group instead, at AddJobsRequest. +// +// These bound what this queue admits. They do not bound sessions started +// outside it, including direct AgentDispatchService.CreateDispatch calls, so +// they are not a cap on an agent's total concurrency. +type DispatchLimit struct { + state protoimpl.MessageState `protogen:"open.v1"` + Scope DispatchLimitScope `protobuf:"varint,1,opt,name=scope,proto3,enum=livekit.DispatchLimitScope" json:"scope,omitempty"` + // Which value of the scoped attribute this limit covers. Empty with a scope + // set means every distinct value gets its own budget of this size, so one + // rule can cover all agents without enumerating them. + Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` + // Jobs from this scope running at once. Unset is unlimited; 0 blocks the + // scope without touching its jobs. + MaxConcurrent *uint32 `protobuf:"varint,4,opt,name=max_concurrent,json=maxConcurrent,proto3,oneof" json:"max_concurrent,omitempty"` + // Dispatch starts allowed in any rolling 60 seconds - not calendar minutes. + // The scheduler releases this budget in slices across admission rounds, so a + // minute's worth never lands at once. Unset is unrated. + MaxStartsPerMinute *uint32 `protobuf:"varint,5,opt,name=max_starts_per_minute,json=maxStartsPerMinute,proto3,oneof" json:"max_starts_per_minute,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DispatchLimit) Reset() { + *x = DispatchLimit{} + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DispatchLimit) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DispatchLimit) ProtoMessage() {} + +func (x *DispatchLimit) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[3] + 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 DispatchLimit.ProtoReflect.Descriptor instead. +func (*DispatchLimit) Descriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{3} +} + +func (x *DispatchLimit) GetScope() DispatchLimitScope { + if x != nil { + return x.Scope + } + return DispatchLimitScope_DISPATCH_LIMIT_SCOPE_UNSPECIFIED +} + +func (x *DispatchLimit) GetKey() string { + if x != nil { + return x.Key + } + return "" +} + +func (x *DispatchLimit) GetMaxConcurrent() uint32 { + if x != nil && x.MaxConcurrent != nil { + return *x.MaxConcurrent + } + return 0 +} + +func (x *DispatchLimit) GetMaxStartsPerMinute() uint32 { + if x != nil && x.MaxStartsPerMinute != nil { + return *x.MaxStartsPerMinute + } + return 0 +} + +type DispatchQueueConfig struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The queue stops admitting while free project capacity would fall below + // this. Everything else the project runs - sessions a user started, direct + // AgentDispatchService.CreateDispatch calls, anything not from this queue - + // draws on the same capacity, and this is what the queue leaves for it. + // + // The asymmetry is the point: a queued job that cannot get capacity waits, + // which is what the queue is for. A request from anywhere else has nowhere + // to wait - it fails with quota exceeded. So the queue must never take the + // project's last capacity, however much it still has to drain. + // + // Size it to the demand you cannot afford to reject, NOT to the peak + // concurrency of that other work - admission already reads capacity + // REMAINING, so steady-state load lowers what the queue may take on its + // own. A project starting 5 sessions/sec wants roughly 10-20 here even if + // it runs 500 at once. + MinFreeCapacity uint32 `protobuf:"varint,1,opt,name=min_free_capacity,json=minFreeCapacity,proto3" json:"min_free_capacity,omitempty"` + Limits []*DispatchLimit `protobuf:"bytes,2,rep,name=limits,proto3" json:"limits,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DispatchQueueConfig) Reset() { + *x = DispatchQueueConfig{} + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DispatchQueueConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DispatchQueueConfig) ProtoMessage() {} + +func (x *DispatchQueueConfig) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[4] + 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 DispatchQueueConfig.ProtoReflect.Descriptor instead. +func (*DispatchQueueConfig) Descriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{4} +} + +func (x *DispatchQueueConfig) GetMinFreeCapacity() uint32 { + if x != nil { + return x.MinFreeCapacity + } + return 0 +} + +func (x *DispatchQueueConfig) GetLimits() []*DispatchLimit { + if x != nil { + return x.Limits + } + return nil +} + +type AddJobsRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Up to 1,000 per request; clients loop to add more. + Jobs []*QueuedJobInput `protobuf:"bytes,1,rep,name=jobs,proto3" json:"jobs,omitempty"` + // Attach every job in this request to a group, created on first use. + GroupId *string `protobuf:"bytes,2,opt,name=group_id,json=groupId,proto3,oneof" json:"group_id,omitempty"` + // Jobs from this group to run at once. Applied when the group is created and + // ignored on later adds to the same group. Unset uses the dispatcher + // default. Group limits live here rather than in DispatchQueueConfig because + // groups are short-lived and would otherwise churn the project config. + GroupConcurrencyLimit *uint32 `protobuf:"varint,3,opt,name=group_concurrency_limit,json=groupConcurrencyLimit,proto3,oneof" json:"group_concurrency_limit,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AddJobsRequest) Reset() { + *x = AddJobsRequest{} + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AddJobsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddJobsRequest) ProtoMessage() {} + +func (x *AddJobsRequest) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[5] + 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 AddJobsRequest.ProtoReflect.Descriptor instead. +func (*AddJobsRequest) Descriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{5} +} + +func (x *AddJobsRequest) GetJobs() []*QueuedJobInput { + if x != nil { + return x.Jobs + } + return nil +} + +func (x *AddJobsRequest) GetGroupId() string { + if x != nil && x.GroupId != nil { + return *x.GroupId + } + return "" +} + +func (x *AddJobsRequest) GetGroupConcurrencyLimit() uint32 { + if x != nil && x.GroupConcurrencyLimit != nil { + return *x.GroupConcurrencyLimit + } + return 0 +} + +type AddJobsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Same order and length as the request. Validation is atomic: if any input + // is invalid nothing is enqueued and the error enumerates every bad entry, + // so a rejected batch is safe to fix and resend in one pass. An input whose + // idempotency_key already existed yields the pre-existing job unchanged. + Jobs []*QueuedJob `protobuf:"bytes,1,rep,name=jobs,proto3" json:"jobs,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AddJobsResponse) Reset() { + *x = AddJobsResponse{} + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AddJobsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddJobsResponse) ProtoMessage() {} + +func (x *AddJobsResponse) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[6] + 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 AddJobsResponse.ProtoReflect.Descriptor instead. +func (*AddJobsResponse) Descriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{6} +} + +func (x *AddJobsResponse) GetJobs() []*QueuedJob { + if x != nil { + return x.Jobs + } + return nil +} + +type GetJobRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + JobId string `protobuf:"bytes,1,opt,name=job_id,json=jobId,proto3" json:"job_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetJobRequest) Reset() { + *x = GetJobRequest{} + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetJobRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetJobRequest) ProtoMessage() {} + +func (x *GetJobRequest) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[7] + 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 GetJobRequest.ProtoReflect.Descriptor instead. +func (*GetJobRequest) Descriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{7} +} + +func (x *GetJobRequest) GetJobId() string { + if x != nil { + return x.JobId + } + return "" +} + +type GetJobResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Job *QueuedJob `protobuf:"bytes,1,opt,name=job,proto3" json:"job,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetJobResponse) Reset() { + *x = GetJobResponse{} + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetJobResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetJobResponse) ProtoMessage() {} + +func (x *GetJobResponse) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[8] + 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 GetJobResponse.ProtoReflect.Descriptor instead. +func (*GetJobResponse) Descriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{8} +} + +func (x *GetJobResponse) GetJob() *QueuedJob { + if x != nil { + return x.Job + } + return nil +} + +type ListJobsRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + GroupId *string `protobuf:"bytes,1,opt,name=group_id,json=groupId,proto3,oneof" json:"group_id,omitempty"` + Status *QueuedJobStatus `protobuf:"varint,2,opt,name=status,proto3,enum=livekit.QueuedJobStatus,oneof" json:"status,omitempty"` + PageToken *TokenPagination `protobuf:"bytes,3,opt,name=page_token,json=pageToken,proto3,oneof" json:"page_token,omitempty"` + PageSize *int32 `protobuf:"varint,4,opt,name=page_size,json=pageSize,proto3,oneof" json:"page_size,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListJobsRequest) Reset() { + *x = ListJobsRequest{} + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListJobsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListJobsRequest) ProtoMessage() {} + +func (x *ListJobsRequest) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[9] + 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 ListJobsRequest.ProtoReflect.Descriptor instead. +func (*ListJobsRequest) Descriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{9} +} + +func (x *ListJobsRequest) GetGroupId() string { + if x != nil && x.GroupId != nil { + return *x.GroupId + } + return "" +} + +func (x *ListJobsRequest) GetStatus() QueuedJobStatus { + if x != nil && x.Status != nil { + return *x.Status + } + return QueuedJobStatus_QUEUED_JOB_STATUS_UNSPECIFIED +} + +func (x *ListJobsRequest) GetPageToken() *TokenPagination { + if x != nil { + return x.PageToken + } + return nil +} + +func (x *ListJobsRequest) GetPageSize() int32 { + if x != nil && x.PageSize != nil { + return *x.PageSize + } + return 0 +} + +type ListJobsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Jobs []*QueuedJob `protobuf:"bytes,1,rep,name=jobs,proto3" json:"jobs,omitempty"` + NextPageToken *TokenPagination `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListJobsResponse) Reset() { + *x = ListJobsResponse{} + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListJobsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListJobsResponse) ProtoMessage() {} + +func (x *ListJobsResponse) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[10] + 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 ListJobsResponse.ProtoReflect.Descriptor instead. +func (*ListJobsResponse) Descriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{10} +} + +func (x *ListJobsResponse) GetJobs() []*QueuedJob { + if x != nil { + return x.Jobs + } + return nil +} + +func (x *ListJobsResponse) GetNextPageToken() *TokenPagination { + if x != nil { + return x.NextPageToken + } + return nil +} + +// Cancels a job that has not been admitted yet (QUEUED -> CANCELLED). A job +// already DISPATCHING or RUNNING is left alone; tear down the live session +// through DeleteDispatch or the room APIs instead. +type RemoveJobRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + JobId string `protobuf:"bytes,1,opt,name=job_id,json=jobId,proto3" json:"job_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RemoveJobRequest) Reset() { + *x = RemoveJobRequest{} + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RemoveJobRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveJobRequest) ProtoMessage() {} + +func (x *RemoveJobRequest) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[11] + 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 RemoveJobRequest.ProtoReflect.Descriptor instead. +func (*RemoveJobRequest) Descriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{11} +} + +func (x *RemoveJobRequest) GetJobId() string { + if x != nil { + return x.JobId + } + return "" +} + +type RemoveJobResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RemoveJobResponse) Reset() { + *x = RemoveJobResponse{} + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RemoveJobResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveJobResponse) ProtoMessage() {} + +func (x *RemoveJobResponse) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[12] + 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 RemoveJobResponse.ProtoReflect.Descriptor instead. +func (*RemoveJobResponse) Descriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{12} +} + +// Re-queues jobs in a FAILED or EXPIRED state, reusing their rows and +// idempotency keys instead of minting new jobs. Jobs in any other state are +// returned untouched. +type RetryJobsRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + JobIds []string `protobuf:"bytes,1,rep,name=job_ids,json=jobIds,proto3" json:"job_ids,omitempty"` + // Replaces expires_at on the retried jobs. + ExpiresAt *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=expires_at,json=expiresAt,proto3,oneof" json:"expires_at,omitempty"` + // Replaces start_after on the retried jobs, to hold a retry back rather than + // re-queueing it immediately. Unset clears any start_after the job carried, + // since the original hold has already elapsed. + StartAfter *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=start_after,json=startAfter,proto3,oneof" json:"start_after,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RetryJobsRequest) Reset() { + *x = RetryJobsRequest{} + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RetryJobsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RetryJobsRequest) ProtoMessage() {} + +func (x *RetryJobsRequest) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[13] + 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 RetryJobsRequest.ProtoReflect.Descriptor instead. +func (*RetryJobsRequest) Descriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{13} +} + +func (x *RetryJobsRequest) GetJobIds() []string { + if x != nil { + return x.JobIds + } + return nil +} + +func (x *RetryJobsRequest) GetExpiresAt() *timestamppb.Timestamp { + if x != nil { + return x.ExpiresAt + } + return nil +} + +func (x *RetryJobsRequest) GetStartAfter() *timestamppb.Timestamp { + if x != nil { + return x.StartAfter + } + return nil +} + +type RetryJobsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Jobs []*QueuedJob `protobuf:"bytes,1,rep,name=jobs,proto3" json:"jobs,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RetryJobsResponse) Reset() { + *x = RetryJobsResponse{} + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RetryJobsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RetryJobsResponse) ProtoMessage() {} + +func (x *RetryJobsResponse) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[14] + 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 RetryJobsResponse.ProtoReflect.Descriptor instead. +func (*RetryJobsResponse) Descriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{14} +} + +func (x *RetryJobsResponse) GetJobs() []*QueuedJob { + if x != nil { + return x.Jobs + } + return nil +} + +type ListJobGroupsRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListJobGroupsRequest) Reset() { + *x = ListJobGroupsRequest{} + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListJobGroupsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListJobGroupsRequest) ProtoMessage() {} + +func (x *ListJobGroupsRequest) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[15] + 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 ListJobGroupsRequest.ProtoReflect.Descriptor instead. +func (*ListJobGroupsRequest) Descriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{15} +} + +type ListJobGroupsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Groups []*JobGroup `protobuf:"bytes,1,rep,name=groups,proto3" json:"groups,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListJobGroupsResponse) Reset() { + *x = ListJobGroupsResponse{} + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListJobGroupsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListJobGroupsResponse) ProtoMessage() {} + +func (x *ListJobGroupsResponse) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[16] + 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 ListJobGroupsResponse.ProtoReflect.Descriptor instead. +func (*ListJobGroupsResponse) Descriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{16} +} + +func (x *ListJobGroupsResponse) GetGroups() []*JobGroup { + if x != nil { + return x.Groups + } + return nil +} + +// On every group operation below, an unset group_id applies the operation at +// project scope, across grouped and ungrouped jobs alike. +type PauseJobGroupRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + GroupId *string `protobuf:"bytes,1,opt,name=group_id,json=groupId,proto3,oneof" json:"group_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PauseJobGroupRequest) Reset() { + *x = PauseJobGroupRequest{} + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PauseJobGroupRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PauseJobGroupRequest) ProtoMessage() {} + +func (x *PauseJobGroupRequest) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[17] + 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 PauseJobGroupRequest.ProtoReflect.Descriptor instead. +func (*PauseJobGroupRequest) Descriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{17} +} + +func (x *PauseJobGroupRequest) GetGroupId() string { + if x != nil && x.GroupId != nil { + return *x.GroupId + } + return "" +} + +type PauseJobGroupResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PauseJobGroupResponse) Reset() { + *x = PauseJobGroupResponse{} + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PauseJobGroupResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PauseJobGroupResponse) ProtoMessage() {} + +func (x *PauseJobGroupResponse) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[18] + 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 PauseJobGroupResponse.ProtoReflect.Descriptor instead. +func (*PauseJobGroupResponse) Descriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{18} +} + +type ResumeJobGroupRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + GroupId *string `protobuf:"bytes,1,opt,name=group_id,json=groupId,proto3,oneof" json:"group_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResumeJobGroupRequest) Reset() { + *x = ResumeJobGroupRequest{} + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResumeJobGroupRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResumeJobGroupRequest) ProtoMessage() {} + +func (x *ResumeJobGroupRequest) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[19] + 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 ResumeJobGroupRequest.ProtoReflect.Descriptor instead. +func (*ResumeJobGroupRequest) Descriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{19} +} + +func (x *ResumeJobGroupRequest) GetGroupId() string { + if x != nil && x.GroupId != nil { + return *x.GroupId + } + return "" +} + +type ResumeJobGroupResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResumeJobGroupResponse) Reset() { + *x = ResumeJobGroupResponse{} + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResumeJobGroupResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResumeJobGroupResponse) ProtoMessage() {} + +func (x *ResumeJobGroupResponse) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[20] + 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 ResumeJobGroupResponse.ProtoReflect.Descriptor instead. +func (*ResumeJobGroupResponse) Descriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{20} +} + +// Cancels the queued jobs in the group; jobs already in flight run to +// completion. +type CancelJobGroupRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + GroupId *string `protobuf:"bytes,1,opt,name=group_id,json=groupId,proto3,oneof" json:"group_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CancelJobGroupRequest) Reset() { + *x = CancelJobGroupRequest{} + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CancelJobGroupRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CancelJobGroupRequest) ProtoMessage() {} + +func (x *CancelJobGroupRequest) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[21] + 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 CancelJobGroupRequest.ProtoReflect.Descriptor instead. +func (*CancelJobGroupRequest) Descriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{21} +} + +func (x *CancelJobGroupRequest) GetGroupId() string { + if x != nil && x.GroupId != nil { + return *x.GroupId + } + return "" +} + +type CancelJobGroupResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CancelJobGroupResponse) Reset() { + *x = CancelJobGroupResponse{} + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CancelJobGroupResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CancelJobGroupResponse) ProtoMessage() {} + +func (x *CancelJobGroupResponse) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_dispatch_queue_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 CancelJobGroupResponse.ProtoReflect.Descriptor instead. +func (*CancelJobGroupResponse) Descriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{22} +} + +// Cancels the remaining queued jobs and hides the group and its terminal jobs +// from listings. Rows are kept for the retention window. +type DeleteJobGroupRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + GroupId *string `protobuf:"bytes,1,opt,name=group_id,json=groupId,proto3,oneof" json:"group_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteJobGroupRequest) Reset() { + *x = DeleteJobGroupRequest{} + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteJobGroupRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteJobGroupRequest) ProtoMessage() {} + +func (x *DeleteJobGroupRequest) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[23] + 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 DeleteJobGroupRequest.ProtoReflect.Descriptor instead. +func (*DeleteJobGroupRequest) Descriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{23} +} + +func (x *DeleteJobGroupRequest) GetGroupId() string { + if x != nil && x.GroupId != nil { + return *x.GroupId + } + return "" +} + +type DeleteJobGroupResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteJobGroupResponse) Reset() { + *x = DeleteJobGroupResponse{} + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteJobGroupResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteJobGroupResponse) ProtoMessage() {} + +func (x *DeleteJobGroupResponse) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[24] + 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 DeleteJobGroupResponse.ProtoReflect.Descriptor instead. +func (*DeleteJobGroupResponse) Descriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{24} +} + +type GetDispatchQueueConfigRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetDispatchQueueConfigRequest) Reset() { + *x = GetDispatchQueueConfigRequest{} + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetDispatchQueueConfigRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetDispatchQueueConfigRequest) ProtoMessage() {} + +func (x *GetDispatchQueueConfigRequest) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[25] + 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 GetDispatchQueueConfigRequest.ProtoReflect.Descriptor instead. +func (*GetDispatchQueueConfigRequest) Descriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{25} +} + +type GetDispatchQueueConfigResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Config *DispatchQueueConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetDispatchQueueConfigResponse) Reset() { + *x = GetDispatchQueueConfigResponse{} + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetDispatchQueueConfigResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetDispatchQueueConfigResponse) ProtoMessage() {} + +func (x *GetDispatchQueueConfigResponse) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[26] + 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 GetDispatchQueueConfigResponse.ProtoReflect.Descriptor instead. +func (*GetDispatchQueueConfigResponse) Descriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{26} +} + +func (x *GetDispatchQueueConfigResponse) GetConfig() *DispatchQueueConfig { + if x != nil { + return x.Config + } + return nil +} + +// Replaces the stored config wholesale, so an omitted limit is a removed +// limit. Read-modify-write to change one field. +type UpdateDispatchQueueConfigRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Config *DispatchQueueConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpdateDispatchQueueConfigRequest) Reset() { + *x = UpdateDispatchQueueConfigRequest{} + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[27] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateDispatchQueueConfigRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateDispatchQueueConfigRequest) ProtoMessage() {} + +func (x *UpdateDispatchQueueConfigRequest) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[27] + 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 UpdateDispatchQueueConfigRequest.ProtoReflect.Descriptor instead. +func (*UpdateDispatchQueueConfigRequest) Descriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{27} +} + +func (x *UpdateDispatchQueueConfigRequest) GetConfig() *DispatchQueueConfig { + if x != nil { + return x.Config + } + return nil +} + +type UpdateDispatchQueueConfigResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Config *DispatchQueueConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpdateDispatchQueueConfigResponse) Reset() { + *x = UpdateDispatchQueueConfigResponse{} + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[28] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateDispatchQueueConfigResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateDispatchQueueConfigResponse) ProtoMessage() {} + +func (x *UpdateDispatchQueueConfigResponse) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[28] + 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 UpdateDispatchQueueConfigResponse.ProtoReflect.Descriptor instead. +func (*UpdateDispatchQueueConfigResponse) Descriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{28} +} + +func (x *UpdateDispatchQueueConfigResponse) GetConfig() *DispatchQueueConfig { + if x != nil { + return x.Config + } + return nil +} + +// Proto3 forbids enum map keys, so counts by status are a repeated pair. +type JobGroup_StatusCount struct { + state protoimpl.MessageState `protogen:"open.v1"` + Status QueuedJobStatus `protobuf:"varint,1,opt,name=status,proto3,enum=livekit.QueuedJobStatus" json:"status,omitempty"` + Count uint32 `protobuf:"varint,2,opt,name=count,proto3" json:"count,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *JobGroup_StatusCount) Reset() { + *x = JobGroup_StatusCount{} + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[30] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *JobGroup_StatusCount) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*JobGroup_StatusCount) ProtoMessage() {} + +func (x *JobGroup_StatusCount) ProtoReflect() protoreflect.Message { + mi := &file_livekit_agent_dispatch_queue_proto_msgTypes[30] + 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 JobGroup_StatusCount.ProtoReflect.Descriptor instead. +func (*JobGroup_StatusCount) Descriptor() ([]byte, []int) { + return file_livekit_agent_dispatch_queue_proto_rawDescGZIP(), []int{2, 0} +} + +func (x *JobGroup_StatusCount) GetStatus() QueuedJobStatus { + if x != nil { + return x.Status + } + return QueuedJobStatus_QUEUED_JOB_STATUS_UNSPECIFIED +} + +func (x *JobGroup_StatusCount) GetCount() uint32 { + if x != nil { + return x.Count + } + return 0 +} + +var File_livekit_agent_dispatch_queue_proto protoreflect.FileDescriptor + +const file_livekit_agent_dispatch_queue_proto_rawDesc = "" + + "\n" + + "\"livekit_agent_dispatch_queue.proto\x12\alivekit\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1clivekit_agent_dispatch.proto\x1a\x14livekit_models.proto\x1a\x14logger/options.proto\"\xda\x04\n" + + "\x0eQueuedJobInput\x12\x1d\n" + + "\n" + + "agent_name\x18\x01 \x01(\tR\tagentName\x12\x1b\n" + + "\troom_name\x18\x02 \x01(\tR\broomName\x12'\n" + + "\x0fidempotency_key\x18\x03 \x01(\tR\x0eidempotencyKey\x12\x1f\n" + + "\bmetadata\x18\x04 \x01(\tB\x03\xc0P\x01R\bmetadata\x12L\n" + + "\n" + + "attributes\x18\x05 \x03(\v2'.livekit.QueuedJobInput.AttributesEntryB\x03\xc0P\x01R\n" + + "attributes\x12\x1e\n" + + "\n" + + "deployment\x18\x06 \x01(\tR\n" + + "deployment\x12@\n" + + "\x0erestart_policy\x18\a \x01(\x0e2\x19.livekit.JobRestartPolicyR\rrestartPolicy\x12>\n" + + "\n" + + "expires_at\x18\b \x01(\v2\x1a.google.protobuf.TimestampH\x00R\texpiresAt\x88\x01\x01\x122\n" + + "\bwebhooks\x18\t \x03(\v2\x16.livekit.WebhookConfigR\bwebhooks\x12@\n" + + "\vstart_after\x18\v \x01(\v2\x1a.google.protobuf.TimestampH\x01R\n" + + "startAfter\x88\x01\x01\x1a=\n" + + "\x0fAttributesEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01B\r\n" + + "\v_expires_atB\x0e\n" + + "\f_start_after\"\x9d\x04\n" + + "\tQueuedJob\x12\x18\n" + + "\x02id\x18\x01 \x01(\tB\b\xbaP\x05jobIDR\x02id\x12*\n" + + "\bgroup_id\x18\x02 \x01(\tB\n" + + "\xbaP\agroupIDH\x00R\agroupId\x88\x01\x01\x120\n" + + "\x06status\x18\x03 \x01(\x0e2\x18.livekit.QueuedJobStatusR\x06status\x12-\n" + + "\x05input\x18\x04 \x01(\v2\x17.livekit.QueuedJobInputR\x05input\x12.\n" + + "\vdispatch_id\x18\x05 \x01(\tB\r\xbaP\n" + + "dispatchIDR\n" + + "dispatchId\x12\"\n" + + "\aroom_id\x18\x06 \x01(\tB\t\xbaP\x06roomIDR\x06roomId\x12\x1b\n" + + "\x06result\x18\a \x01(\tB\x03\xc0P\x01R\x06result\x12\x14\n" + + "\x05error\x18\b \x01(\tR\x05error\x12\x1a\n" + + "\battempts\x18\t \x01(\x05R\battempts\x129\n" + + "\n" + + "created_at\x18\n" + + " \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\x12?\n" + + "\rdispatched_at\x18\v \x01(\v2\x1a.google.protobuf.TimestampR\fdispatchedAt\x12=\n" + + "\fcompleted_at\x18\f \x01(\v2\x1a.google.protobuf.TimestampR\vcompletedAtB\v\n" + + "\t_group_id\"\xb4\x02\n" + + "\bJobGroup\x12\x1a\n" + + "\x02id\x18\x01 \x01(\tB\n" + + "\xbaP\agroupIDR\x02id\x12\x16\n" + + "\x06paused\x18\x02 \x01(\bR\x06paused\x129\n" + + "\n" + + "created_at\x18\x03 \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\x125\n" + + "\x06counts\x18\x04 \x03(\v2\x1d.livekit.JobGroup.StatusCountR\x06counts\x12+\n" + + "\x11concurrency_limit\x18\x05 \x01(\rR\x10concurrencyLimit\x1aU\n" + + "\vStatusCount\x120\n" + + "\x06status\x18\x01 \x01(\x0e2\x18.livekit.QueuedJobStatusR\x06status\x12\x14\n" + + "\x05count\x18\x02 \x01(\rR\x05count\"\xe5\x01\n" + + "\rDispatchLimit\x121\n" + + "\x05scope\x18\x01 \x01(\x0e2\x1b.livekit.DispatchLimitScopeR\x05scope\x12\x10\n" + + "\x03key\x18\x02 \x01(\tR\x03key\x12*\n" + + "\x0emax_concurrent\x18\x04 \x01(\rH\x00R\rmaxConcurrent\x88\x01\x01\x126\n" + + "\x15max_starts_per_minute\x18\x05 \x01(\rH\x01R\x12maxStartsPerMinute\x88\x01\x01B\x11\n" + + "\x0f_max_concurrentB\x18\n" + + "\x16_max_starts_per_minute\"q\n" + + "\x13DispatchQueueConfig\x12*\n" + + "\x11min_free_capacity\x18\x01 \x01(\rR\x0fminFreeCapacity\x12.\n" + + "\x06limits\x18\x02 \x03(\v2\x16.livekit.DispatchLimitR\x06limits\"\xcf\x01\n" + + "\x0eAddJobsRequest\x12+\n" + + "\x04jobs\x18\x01 \x03(\v2\x17.livekit.QueuedJobInputR\x04jobs\x12*\n" + + "\bgroup_id\x18\x02 \x01(\tB\n" + + "\xbaP\agroupIDH\x00R\agroupId\x88\x01\x01\x12;\n" + + "\x17group_concurrency_limit\x18\x03 \x01(\rH\x01R\x15groupConcurrencyLimit\x88\x01\x01B\v\n" + + "\t_group_idB\x1a\n" + + "\x18_group_concurrency_limit\"9\n" + + "\x0fAddJobsResponse\x12&\n" + + "\x04jobs\x18\x01 \x03(\v2\x12.livekit.QueuedJobR\x04jobs\"0\n" + + "\rGetJobRequest\x12\x1f\n" + + "\x06job_id\x18\x01 \x01(\tB\b\xbaP\x05jobIDR\x05jobId\"6\n" + + "\x0eGetJobResponse\x12$\n" + + "\x03job\x18\x01 \x01(\v2\x12.livekit.QueuedJobR\x03job\"\x89\x02\n" + + "\x0fListJobsRequest\x12*\n" + + "\bgroup_id\x18\x01 \x01(\tB\n" + + "\xbaP\agroupIDH\x00R\agroupId\x88\x01\x01\x125\n" + + "\x06status\x18\x02 \x01(\x0e2\x18.livekit.QueuedJobStatusH\x01R\x06status\x88\x01\x01\x12<\n" + + "\n" + + "page_token\x18\x03 \x01(\v2\x18.livekit.TokenPaginationH\x02R\tpageToken\x88\x01\x01\x12 \n" + + "\tpage_size\x18\x04 \x01(\x05H\x03R\bpageSize\x88\x01\x01B\v\n" + + "\t_group_idB\t\n" + + "\a_statusB\r\n" + + "\v_page_tokenB\f\n" + + "\n" + + "_page_size\"|\n" + + "\x10ListJobsResponse\x12&\n" + + "\x04jobs\x18\x01 \x03(\v2\x12.livekit.QueuedJobR\x04jobs\x12@\n" + + "\x0fnext_page_token\x18\x02 \x01(\v2\x18.livekit.TokenPaginationR\rnextPageToken\"3\n" + + "\x10RemoveJobRequest\x12\x1f\n" + + "\x06job_id\x18\x01 \x01(\tB\b\xbaP\x05jobIDR\x05jobId\"\x13\n" + + "\x11RemoveJobResponse\"\xd7\x01\n" + + "\x10RetryJobsRequest\x12\"\n" + + "\ajob_ids\x18\x01 \x03(\tB\t\xbaP\x06jobIDsR\x06jobIds\x12>\n" + + "\n" + + "expires_at\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampH\x00R\texpiresAt\x88\x01\x01\x12@\n" + + "\vstart_after\x18\x03 \x01(\v2\x1a.google.protobuf.TimestampH\x01R\n" + + "startAfter\x88\x01\x01B\r\n" + + "\v_expires_atB\x0e\n" + + "\f_start_after\";\n" + + "\x11RetryJobsResponse\x12&\n" + + "\x04jobs\x18\x01 \x03(\v2\x12.livekit.QueuedJobR\x04jobs\"\x16\n" + + "\x14ListJobGroupsRequest\"B\n" + + "\x15ListJobGroupsResponse\x12)\n" + + "\x06groups\x18\x01 \x03(\v2\x11.livekit.JobGroupR\x06groups\"O\n" + + "\x14PauseJobGroupRequest\x12*\n" + + "\bgroup_id\x18\x01 \x01(\tB\n" + + "\xbaP\agroupIDH\x00R\agroupId\x88\x01\x01B\v\n" + + "\t_group_id\"\x17\n" + + "\x15PauseJobGroupResponse\"P\n" + + "\x15ResumeJobGroupRequest\x12*\n" + + "\bgroup_id\x18\x01 \x01(\tB\n" + + "\xbaP\agroupIDH\x00R\agroupId\x88\x01\x01B\v\n" + + "\t_group_id\"\x18\n" + + "\x16ResumeJobGroupResponse\"P\n" + + "\x15CancelJobGroupRequest\x12*\n" + + "\bgroup_id\x18\x01 \x01(\tB\n" + + "\xbaP\agroupIDH\x00R\agroupId\x88\x01\x01B\v\n" + + "\t_group_id\"\x18\n" + + "\x16CancelJobGroupResponse\"P\n" + + "\x15DeleteJobGroupRequest\x12*\n" + + "\bgroup_id\x18\x01 \x01(\tB\n" + + "\xbaP\agroupIDH\x00R\agroupId\x88\x01\x01B\v\n" + + "\t_group_id\"\x18\n" + + "\x16DeleteJobGroupResponse\"\x1f\n" + + "\x1dGetDispatchQueueConfigRequest\"V\n" + + "\x1eGetDispatchQueueConfigResponse\x124\n" + + "\x06config\x18\x01 \x01(\v2\x1c.livekit.DispatchQueueConfigR\x06config\"X\n" + + " UpdateDispatchQueueConfigRequest\x124\n" + + "\x06config\x18\x01 \x01(\v2\x1c.livekit.DispatchQueueConfigR\x06config\"Y\n" + + "!UpdateDispatchQueueConfigResponse\x124\n" + + "\x06config\x18\x01 \x01(\v2\x1c.livekit.DispatchQueueConfigR\x06config*\x93\x02\n" + + "\x0fQueuedJobStatus\x12!\n" + + "\x1dQUEUED_JOB_STATUS_UNSPECIFIED\x10\x00\x12\x1c\n" + + "\x18QUEUED_JOB_STATUS_QUEUED\x10\x01\x12!\n" + + "\x1dQUEUED_JOB_STATUS_DISPATCHING\x10\x02\x12\x1d\n" + + "\x19QUEUED_JOB_STATUS_RUNNING\x10\x03\x12\x1f\n" + + "\x1bQUEUED_JOB_STATUS_SUCCEEDED\x10\x04\x12\x1c\n" + + "\x18QUEUED_JOB_STATUS_FAILED\x10\x05\x12\x1f\n" + + "\x1bQUEUED_JOB_STATUS_CANCELLED\x10\x06\x12\x1d\n" + + "\x19QUEUED_JOB_STATUS_EXPIRED\x10\a*Z\n" + + "\x12DispatchLimitScope\x12$\n" + + " DISPATCH_LIMIT_SCOPE_UNSPECIFIED\x10\x00\x12\x1e\n" + + "\x1aDISPATCH_LIMIT_SCOPE_AGENT\x10\x012\xce\a\n" + + "\x12AgentDispatchQueue\x12<\n" + + "\aAddJobs\x12\x17.livekit.AddJobsRequest\x1a\x18.livekit.AddJobsResponse\x129\n" + + "\x06GetJob\x12\x16.livekit.GetJobRequest\x1a\x17.livekit.GetJobResponse\x12?\n" + + "\bListJobs\x12\x18.livekit.ListJobsRequest\x1a\x19.livekit.ListJobsResponse\x12B\n" + + "\tRemoveJob\x12\x19.livekit.RemoveJobRequest\x1a\x1a.livekit.RemoveJobResponse\x12B\n" + + "\tRetryJobs\x12\x19.livekit.RetryJobsRequest\x1a\x1a.livekit.RetryJobsResponse\x12N\n" + + "\rListJobGroups\x12\x1d.livekit.ListJobGroupsRequest\x1a\x1e.livekit.ListJobGroupsResponse\x12N\n" + + "\rPauseJobGroup\x12\x1d.livekit.PauseJobGroupRequest\x1a\x1e.livekit.PauseJobGroupResponse\x12Q\n" + + "\x0eResumeJobGroup\x12\x1e.livekit.ResumeJobGroupRequest\x1a\x1f.livekit.ResumeJobGroupResponse\x12Q\n" + + "\x0eCancelJobGroup\x12\x1e.livekit.CancelJobGroupRequest\x1a\x1f.livekit.CancelJobGroupResponse\x12Q\n" + + "\x0eDeleteJobGroup\x12\x1e.livekit.DeleteJobGroupRequest\x1a\x1f.livekit.DeleteJobGroupResponse\x12i\n" + + "\x16GetDispatchQueueConfig\x12&.livekit.GetDispatchQueueConfigRequest\x1a'.livekit.GetDispatchQueueConfigResponse\x12r\n" + + "\x19UpdateDispatchQueueConfig\x12).livekit.UpdateDispatchQueueConfigRequest\x1a*.livekit.UpdateDispatchQueueConfigResponseBFZ#github.com/livekit/protocol/livekit\xaa\x02\rLiveKit.Proto\xea\x02\x0eLiveKit::Protob\x06proto3" + +var ( + file_livekit_agent_dispatch_queue_proto_rawDescOnce sync.Once + file_livekit_agent_dispatch_queue_proto_rawDescData []byte +) + +func file_livekit_agent_dispatch_queue_proto_rawDescGZIP() []byte { + file_livekit_agent_dispatch_queue_proto_rawDescOnce.Do(func() { + file_livekit_agent_dispatch_queue_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_livekit_agent_dispatch_queue_proto_rawDesc), len(file_livekit_agent_dispatch_queue_proto_rawDesc))) + }) + return file_livekit_agent_dispatch_queue_proto_rawDescData +} + +var file_livekit_agent_dispatch_queue_proto_enumTypes = make([]protoimpl.EnumInfo, 2) +var file_livekit_agent_dispatch_queue_proto_msgTypes = make([]protoimpl.MessageInfo, 31) +var file_livekit_agent_dispatch_queue_proto_goTypes = []any{ + (QueuedJobStatus)(0), // 0: livekit.QueuedJobStatus + (DispatchLimitScope)(0), // 1: livekit.DispatchLimitScope + (*QueuedJobInput)(nil), // 2: livekit.QueuedJobInput + (*QueuedJob)(nil), // 3: livekit.QueuedJob + (*JobGroup)(nil), // 4: livekit.JobGroup + (*DispatchLimit)(nil), // 5: livekit.DispatchLimit + (*DispatchQueueConfig)(nil), // 6: livekit.DispatchQueueConfig + (*AddJobsRequest)(nil), // 7: livekit.AddJobsRequest + (*AddJobsResponse)(nil), // 8: livekit.AddJobsResponse + (*GetJobRequest)(nil), // 9: livekit.GetJobRequest + (*GetJobResponse)(nil), // 10: livekit.GetJobResponse + (*ListJobsRequest)(nil), // 11: livekit.ListJobsRequest + (*ListJobsResponse)(nil), // 12: livekit.ListJobsResponse + (*RemoveJobRequest)(nil), // 13: livekit.RemoveJobRequest + (*RemoveJobResponse)(nil), // 14: livekit.RemoveJobResponse + (*RetryJobsRequest)(nil), // 15: livekit.RetryJobsRequest + (*RetryJobsResponse)(nil), // 16: livekit.RetryJobsResponse + (*ListJobGroupsRequest)(nil), // 17: livekit.ListJobGroupsRequest + (*ListJobGroupsResponse)(nil), // 18: livekit.ListJobGroupsResponse + (*PauseJobGroupRequest)(nil), // 19: livekit.PauseJobGroupRequest + (*PauseJobGroupResponse)(nil), // 20: livekit.PauseJobGroupResponse + (*ResumeJobGroupRequest)(nil), // 21: livekit.ResumeJobGroupRequest + (*ResumeJobGroupResponse)(nil), // 22: livekit.ResumeJobGroupResponse + (*CancelJobGroupRequest)(nil), // 23: livekit.CancelJobGroupRequest + (*CancelJobGroupResponse)(nil), // 24: livekit.CancelJobGroupResponse + (*DeleteJobGroupRequest)(nil), // 25: livekit.DeleteJobGroupRequest + (*DeleteJobGroupResponse)(nil), // 26: livekit.DeleteJobGroupResponse + (*GetDispatchQueueConfigRequest)(nil), // 27: livekit.GetDispatchQueueConfigRequest + (*GetDispatchQueueConfigResponse)(nil), // 28: livekit.GetDispatchQueueConfigResponse + (*UpdateDispatchQueueConfigRequest)(nil), // 29: livekit.UpdateDispatchQueueConfigRequest + (*UpdateDispatchQueueConfigResponse)(nil), // 30: livekit.UpdateDispatchQueueConfigResponse + nil, // 31: livekit.QueuedJobInput.AttributesEntry + (*JobGroup_StatusCount)(nil), // 32: livekit.JobGroup.StatusCount + (JobRestartPolicy)(0), // 33: livekit.JobRestartPolicy + (*timestamppb.Timestamp)(nil), // 34: google.protobuf.Timestamp + (*WebhookConfig)(nil), // 35: livekit.WebhookConfig + (*TokenPagination)(nil), // 36: livekit.TokenPagination +} +var file_livekit_agent_dispatch_queue_proto_depIdxs = []int32{ + 31, // 0: livekit.QueuedJobInput.attributes:type_name -> livekit.QueuedJobInput.AttributesEntry + 33, // 1: livekit.QueuedJobInput.restart_policy:type_name -> livekit.JobRestartPolicy + 34, // 2: livekit.QueuedJobInput.expires_at:type_name -> google.protobuf.Timestamp + 35, // 3: livekit.QueuedJobInput.webhooks:type_name -> livekit.WebhookConfig + 34, // 4: livekit.QueuedJobInput.start_after:type_name -> google.protobuf.Timestamp + 0, // 5: livekit.QueuedJob.status:type_name -> livekit.QueuedJobStatus + 2, // 6: livekit.QueuedJob.input:type_name -> livekit.QueuedJobInput + 34, // 7: livekit.QueuedJob.created_at:type_name -> google.protobuf.Timestamp + 34, // 8: livekit.QueuedJob.dispatched_at:type_name -> google.protobuf.Timestamp + 34, // 9: livekit.QueuedJob.completed_at:type_name -> google.protobuf.Timestamp + 34, // 10: livekit.JobGroup.created_at:type_name -> google.protobuf.Timestamp + 32, // 11: livekit.JobGroup.counts:type_name -> livekit.JobGroup.StatusCount + 1, // 12: livekit.DispatchLimit.scope:type_name -> livekit.DispatchLimitScope + 5, // 13: livekit.DispatchQueueConfig.limits:type_name -> livekit.DispatchLimit + 2, // 14: livekit.AddJobsRequest.jobs:type_name -> livekit.QueuedJobInput + 3, // 15: livekit.AddJobsResponse.jobs:type_name -> livekit.QueuedJob + 3, // 16: livekit.GetJobResponse.job:type_name -> livekit.QueuedJob + 0, // 17: livekit.ListJobsRequest.status:type_name -> livekit.QueuedJobStatus + 36, // 18: livekit.ListJobsRequest.page_token:type_name -> livekit.TokenPagination + 3, // 19: livekit.ListJobsResponse.jobs:type_name -> livekit.QueuedJob + 36, // 20: livekit.ListJobsResponse.next_page_token:type_name -> livekit.TokenPagination + 34, // 21: livekit.RetryJobsRequest.expires_at:type_name -> google.protobuf.Timestamp + 34, // 22: livekit.RetryJobsRequest.start_after:type_name -> google.protobuf.Timestamp + 3, // 23: livekit.RetryJobsResponse.jobs:type_name -> livekit.QueuedJob + 4, // 24: livekit.ListJobGroupsResponse.groups:type_name -> livekit.JobGroup + 6, // 25: livekit.GetDispatchQueueConfigResponse.config:type_name -> livekit.DispatchQueueConfig + 6, // 26: livekit.UpdateDispatchQueueConfigRequest.config:type_name -> livekit.DispatchQueueConfig + 6, // 27: livekit.UpdateDispatchQueueConfigResponse.config:type_name -> livekit.DispatchQueueConfig + 0, // 28: livekit.JobGroup.StatusCount.status:type_name -> livekit.QueuedJobStatus + 7, // 29: livekit.AgentDispatchQueue.AddJobs:input_type -> livekit.AddJobsRequest + 9, // 30: livekit.AgentDispatchQueue.GetJob:input_type -> livekit.GetJobRequest + 11, // 31: livekit.AgentDispatchQueue.ListJobs:input_type -> livekit.ListJobsRequest + 13, // 32: livekit.AgentDispatchQueue.RemoveJob:input_type -> livekit.RemoveJobRequest + 15, // 33: livekit.AgentDispatchQueue.RetryJobs:input_type -> livekit.RetryJobsRequest + 17, // 34: livekit.AgentDispatchQueue.ListJobGroups:input_type -> livekit.ListJobGroupsRequest + 19, // 35: livekit.AgentDispatchQueue.PauseJobGroup:input_type -> livekit.PauseJobGroupRequest + 21, // 36: livekit.AgentDispatchQueue.ResumeJobGroup:input_type -> livekit.ResumeJobGroupRequest + 23, // 37: livekit.AgentDispatchQueue.CancelJobGroup:input_type -> livekit.CancelJobGroupRequest + 25, // 38: livekit.AgentDispatchQueue.DeleteJobGroup:input_type -> livekit.DeleteJobGroupRequest + 27, // 39: livekit.AgentDispatchQueue.GetDispatchQueueConfig:input_type -> livekit.GetDispatchQueueConfigRequest + 29, // 40: livekit.AgentDispatchQueue.UpdateDispatchQueueConfig:input_type -> livekit.UpdateDispatchQueueConfigRequest + 8, // 41: livekit.AgentDispatchQueue.AddJobs:output_type -> livekit.AddJobsResponse + 10, // 42: livekit.AgentDispatchQueue.GetJob:output_type -> livekit.GetJobResponse + 12, // 43: livekit.AgentDispatchQueue.ListJobs:output_type -> livekit.ListJobsResponse + 14, // 44: livekit.AgentDispatchQueue.RemoveJob:output_type -> livekit.RemoveJobResponse + 16, // 45: livekit.AgentDispatchQueue.RetryJobs:output_type -> livekit.RetryJobsResponse + 18, // 46: livekit.AgentDispatchQueue.ListJobGroups:output_type -> livekit.ListJobGroupsResponse + 20, // 47: livekit.AgentDispatchQueue.PauseJobGroup:output_type -> livekit.PauseJobGroupResponse + 22, // 48: livekit.AgentDispatchQueue.ResumeJobGroup:output_type -> livekit.ResumeJobGroupResponse + 24, // 49: livekit.AgentDispatchQueue.CancelJobGroup:output_type -> livekit.CancelJobGroupResponse + 26, // 50: livekit.AgentDispatchQueue.DeleteJobGroup:output_type -> livekit.DeleteJobGroupResponse + 28, // 51: livekit.AgentDispatchQueue.GetDispatchQueueConfig:output_type -> livekit.GetDispatchQueueConfigResponse + 30, // 52: livekit.AgentDispatchQueue.UpdateDispatchQueueConfig:output_type -> livekit.UpdateDispatchQueueConfigResponse + 41, // [41:53] is the sub-list for method output_type + 29, // [29:41] is the sub-list for method input_type + 29, // [29:29] is the sub-list for extension type_name + 29, // [29:29] is the sub-list for extension extendee + 0, // [0:29] is the sub-list for field type_name +} + +func init() { file_livekit_agent_dispatch_queue_proto_init() } +func file_livekit_agent_dispatch_queue_proto_init() { + if File_livekit_agent_dispatch_queue_proto != nil { + return + } + file_livekit_agent_dispatch_proto_init() + file_livekit_models_proto_init() + file_livekit_agent_dispatch_queue_proto_msgTypes[0].OneofWrappers = []any{} + file_livekit_agent_dispatch_queue_proto_msgTypes[1].OneofWrappers = []any{} + file_livekit_agent_dispatch_queue_proto_msgTypes[3].OneofWrappers = []any{} + file_livekit_agent_dispatch_queue_proto_msgTypes[5].OneofWrappers = []any{} + file_livekit_agent_dispatch_queue_proto_msgTypes[9].OneofWrappers = []any{} + file_livekit_agent_dispatch_queue_proto_msgTypes[13].OneofWrappers = []any{} + file_livekit_agent_dispatch_queue_proto_msgTypes[17].OneofWrappers = []any{} + file_livekit_agent_dispatch_queue_proto_msgTypes[19].OneofWrappers = []any{} + file_livekit_agent_dispatch_queue_proto_msgTypes[21].OneofWrappers = []any{} + file_livekit_agent_dispatch_queue_proto_msgTypes[23].OneofWrappers = []any{} + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_livekit_agent_dispatch_queue_proto_rawDesc), len(file_livekit_agent_dispatch_queue_proto_rawDesc)), + NumEnums: 2, + NumMessages: 31, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_livekit_agent_dispatch_queue_proto_goTypes, + DependencyIndexes: file_livekit_agent_dispatch_queue_proto_depIdxs, + EnumInfos: file_livekit_agent_dispatch_queue_proto_enumTypes, + MessageInfos: file_livekit_agent_dispatch_queue_proto_msgTypes, + }.Build() + File_livekit_agent_dispatch_queue_proto = out.File + file_livekit_agent_dispatch_queue_proto_goTypes = nil + file_livekit_agent_dispatch_queue_proto_depIdxs = nil +} diff --git a/livekit/livekit_agent_dispatch_queue.twirp.go b/livekit/livekit_agent_dispatch_queue.twirp.go new file mode 100644 index 000000000..a4a6c30f6 --- /dev/null +++ b/livekit/livekit_agent_dispatch_queue.twirp.go @@ -0,0 +1,3716 @@ +// Code generated by protoc-gen-twirp v8.1.3, DO NOT EDIT. +// source: livekit_agent_dispatch_queue.proto + +package livekit + +import context "context" +import fmt "fmt" +import http "net/http" +import io "io" +import json "encoding/json" +import strconv "strconv" +import strings "strings" + +import protojson "google.golang.org/protobuf/encoding/protojson" +import proto "google.golang.org/protobuf/proto" +import twirp "github.com/twitchtv/twirp" +import ctxsetters "github.com/twitchtv/twirp/ctxsetters" + +// Version compatibility assertion. +// If the constant is not defined in the package, that likely means +// the package needs to be updated to work with this generated code. +// See https://twitchtv.github.io/twirp/docs/version_matrix.html +const _ = twirp.TwirpPackageMinVersion_8_1_0 + +// ============================ +// AgentDispatchQueue Interface +// ============================ + +// AgentDispatchQueue accepts dispatches to run later, as project capacity +// allows, instead of failing at the concurrency cap the way +// AgentDispatchService.CreateDispatch does. A queued job becomes a real +// AgentDispatch only once the queue admits it. +// +// Enqueue is a batch because the queue exists to take thousands of dispatches +// in one request and let admission control pace them against the project's +// remaining capacity. +// +// Implemented in cloud only; OSS livekit-server does not serve this service. +// The project is taken from the caller's credentials, never from the request. +type AgentDispatchQueue interface { + AddJobs(context.Context, *AddJobsRequest) (*AddJobsResponse, error) + + GetJob(context.Context, *GetJobRequest) (*GetJobResponse, error) + + ListJobs(context.Context, *ListJobsRequest) (*ListJobsResponse, error) + + RemoveJob(context.Context, *RemoveJobRequest) (*RemoveJobResponse, error) + + RetryJobs(context.Context, *RetryJobsRequest) (*RetryJobsResponse, error) + + // Group operations. The server returns Unimplemented for all five until the + // group model lands (AP-976). + ListJobGroups(context.Context, *ListJobGroupsRequest) (*ListJobGroupsResponse, error) + + PauseJobGroup(context.Context, *PauseJobGroupRequest) (*PauseJobGroupResponse, error) + + ResumeJobGroup(context.Context, *ResumeJobGroupRequest) (*ResumeJobGroupResponse, error) + + CancelJobGroup(context.Context, *CancelJobGroupRequest) (*CancelJobGroupResponse, error) + + DeleteJobGroup(context.Context, *DeleteJobGroupRequest) (*DeleteJobGroupResponse, error) + + GetDispatchQueueConfig(context.Context, *GetDispatchQueueConfigRequest) (*GetDispatchQueueConfigResponse, error) + + UpdateDispatchQueueConfig(context.Context, *UpdateDispatchQueueConfigRequest) (*UpdateDispatchQueueConfigResponse, error) +} + +// ================================== +// AgentDispatchQueue Protobuf Client +// ================================== + +type agentDispatchQueueProtobufClient struct { + client HTTPClient + urls [12]string + interceptor twirp.Interceptor + opts twirp.ClientOptions +} + +// NewAgentDispatchQueueProtobufClient creates a Protobuf client that implements the AgentDispatchQueue interface. +// It communicates using Protobuf and can be configured with a custom HTTPClient. +func NewAgentDispatchQueueProtobufClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) AgentDispatchQueue { + if c, ok := client.(*http.Client); ok { + client = withoutRedirects(c) + } + + clientOpts := twirp.ClientOptions{} + for _, o := range opts { + o(&clientOpts) + } + + // Using ReadOpt allows backwards and forwards compatibility with new options in the future + literalURLs := false + _ = clientOpts.ReadOpt("literalURLs", &literalURLs) + var pathPrefix string + if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { + pathPrefix = "/twirp" // default prefix + } + + // Build method URLs: []/./ + serviceURL := sanitizeBaseURL(baseURL) + serviceURL += baseServicePath(pathPrefix, "livekit", "AgentDispatchQueue") + urls := [12]string{ + serviceURL + "AddJobs", + serviceURL + "GetJob", + serviceURL + "ListJobs", + serviceURL + "RemoveJob", + serviceURL + "RetryJobs", + serviceURL + "ListJobGroups", + serviceURL + "PauseJobGroup", + serviceURL + "ResumeJobGroup", + serviceURL + "CancelJobGroup", + serviceURL + "DeleteJobGroup", + serviceURL + "GetDispatchQueueConfig", + serviceURL + "UpdateDispatchQueueConfig", + } + + return &agentDispatchQueueProtobufClient{ + client: client, + urls: urls, + interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), + opts: clientOpts, + } +} + +func (c *agentDispatchQueueProtobufClient) AddJobs(ctx context.Context, in *AddJobsRequest) (*AddJobsResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentDispatchQueue") + ctx = ctxsetters.WithMethodName(ctx, "AddJobs") + caller := c.callAddJobs + if c.interceptor != nil { + caller = func(ctx context.Context, req *AddJobsRequest) (*AddJobsResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*AddJobsRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*AddJobsRequest) when calling interceptor") + } + return c.callAddJobs(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*AddJobsResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*AddJobsResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentDispatchQueueProtobufClient) callAddJobs(ctx context.Context, in *AddJobsRequest) (*AddJobsResponse, error) { + out := new(AddJobsResponse) + ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +func (c *agentDispatchQueueProtobufClient) GetJob(ctx context.Context, in *GetJobRequest) (*GetJobResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentDispatchQueue") + ctx = ctxsetters.WithMethodName(ctx, "GetJob") + caller := c.callGetJob + if c.interceptor != nil { + caller = func(ctx context.Context, req *GetJobRequest) (*GetJobResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*GetJobRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*GetJobRequest) when calling interceptor") + } + return c.callGetJob(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*GetJobResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*GetJobResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentDispatchQueueProtobufClient) callGetJob(ctx context.Context, in *GetJobRequest) (*GetJobResponse, error) { + out := new(GetJobResponse) + ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[1], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +func (c *agentDispatchQueueProtobufClient) ListJobs(ctx context.Context, in *ListJobsRequest) (*ListJobsResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentDispatchQueue") + ctx = ctxsetters.WithMethodName(ctx, "ListJobs") + caller := c.callListJobs + if c.interceptor != nil { + caller = func(ctx context.Context, req *ListJobsRequest) (*ListJobsResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*ListJobsRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*ListJobsRequest) when calling interceptor") + } + return c.callListJobs(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*ListJobsResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*ListJobsResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentDispatchQueueProtobufClient) callListJobs(ctx context.Context, in *ListJobsRequest) (*ListJobsResponse, error) { + out := new(ListJobsResponse) + ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[2], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +func (c *agentDispatchQueueProtobufClient) RemoveJob(ctx context.Context, in *RemoveJobRequest) (*RemoveJobResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentDispatchQueue") + ctx = ctxsetters.WithMethodName(ctx, "RemoveJob") + caller := c.callRemoveJob + if c.interceptor != nil { + caller = func(ctx context.Context, req *RemoveJobRequest) (*RemoveJobResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*RemoveJobRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*RemoveJobRequest) when calling interceptor") + } + return c.callRemoveJob(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*RemoveJobResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*RemoveJobResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentDispatchQueueProtobufClient) callRemoveJob(ctx context.Context, in *RemoveJobRequest) (*RemoveJobResponse, error) { + out := new(RemoveJobResponse) + ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[3], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +func (c *agentDispatchQueueProtobufClient) RetryJobs(ctx context.Context, in *RetryJobsRequest) (*RetryJobsResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentDispatchQueue") + ctx = ctxsetters.WithMethodName(ctx, "RetryJobs") + caller := c.callRetryJobs + if c.interceptor != nil { + caller = func(ctx context.Context, req *RetryJobsRequest) (*RetryJobsResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*RetryJobsRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*RetryJobsRequest) when calling interceptor") + } + return c.callRetryJobs(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*RetryJobsResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*RetryJobsResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentDispatchQueueProtobufClient) callRetryJobs(ctx context.Context, in *RetryJobsRequest) (*RetryJobsResponse, error) { + out := new(RetryJobsResponse) + ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[4], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +func (c *agentDispatchQueueProtobufClient) ListJobGroups(ctx context.Context, in *ListJobGroupsRequest) (*ListJobGroupsResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentDispatchQueue") + ctx = ctxsetters.WithMethodName(ctx, "ListJobGroups") + caller := c.callListJobGroups + if c.interceptor != nil { + caller = func(ctx context.Context, req *ListJobGroupsRequest) (*ListJobGroupsResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*ListJobGroupsRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*ListJobGroupsRequest) when calling interceptor") + } + return c.callListJobGroups(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*ListJobGroupsResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*ListJobGroupsResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentDispatchQueueProtobufClient) callListJobGroups(ctx context.Context, in *ListJobGroupsRequest) (*ListJobGroupsResponse, error) { + out := new(ListJobGroupsResponse) + ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[5], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +func (c *agentDispatchQueueProtobufClient) PauseJobGroup(ctx context.Context, in *PauseJobGroupRequest) (*PauseJobGroupResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentDispatchQueue") + ctx = ctxsetters.WithMethodName(ctx, "PauseJobGroup") + caller := c.callPauseJobGroup + if c.interceptor != nil { + caller = func(ctx context.Context, req *PauseJobGroupRequest) (*PauseJobGroupResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*PauseJobGroupRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*PauseJobGroupRequest) when calling interceptor") + } + return c.callPauseJobGroup(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*PauseJobGroupResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*PauseJobGroupResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentDispatchQueueProtobufClient) callPauseJobGroup(ctx context.Context, in *PauseJobGroupRequest) (*PauseJobGroupResponse, error) { + out := new(PauseJobGroupResponse) + ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[6], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +func (c *agentDispatchQueueProtobufClient) ResumeJobGroup(ctx context.Context, in *ResumeJobGroupRequest) (*ResumeJobGroupResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentDispatchQueue") + ctx = ctxsetters.WithMethodName(ctx, "ResumeJobGroup") + caller := c.callResumeJobGroup + if c.interceptor != nil { + caller = func(ctx context.Context, req *ResumeJobGroupRequest) (*ResumeJobGroupResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*ResumeJobGroupRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*ResumeJobGroupRequest) when calling interceptor") + } + return c.callResumeJobGroup(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*ResumeJobGroupResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*ResumeJobGroupResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentDispatchQueueProtobufClient) callResumeJobGroup(ctx context.Context, in *ResumeJobGroupRequest) (*ResumeJobGroupResponse, error) { + out := new(ResumeJobGroupResponse) + ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[7], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +func (c *agentDispatchQueueProtobufClient) CancelJobGroup(ctx context.Context, in *CancelJobGroupRequest) (*CancelJobGroupResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentDispatchQueue") + ctx = ctxsetters.WithMethodName(ctx, "CancelJobGroup") + caller := c.callCancelJobGroup + if c.interceptor != nil { + caller = func(ctx context.Context, req *CancelJobGroupRequest) (*CancelJobGroupResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*CancelJobGroupRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*CancelJobGroupRequest) when calling interceptor") + } + return c.callCancelJobGroup(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*CancelJobGroupResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*CancelJobGroupResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentDispatchQueueProtobufClient) callCancelJobGroup(ctx context.Context, in *CancelJobGroupRequest) (*CancelJobGroupResponse, error) { + out := new(CancelJobGroupResponse) + ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[8], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +func (c *agentDispatchQueueProtobufClient) DeleteJobGroup(ctx context.Context, in *DeleteJobGroupRequest) (*DeleteJobGroupResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentDispatchQueue") + ctx = ctxsetters.WithMethodName(ctx, "DeleteJobGroup") + caller := c.callDeleteJobGroup + if c.interceptor != nil { + caller = func(ctx context.Context, req *DeleteJobGroupRequest) (*DeleteJobGroupResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*DeleteJobGroupRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*DeleteJobGroupRequest) when calling interceptor") + } + return c.callDeleteJobGroup(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*DeleteJobGroupResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*DeleteJobGroupResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentDispatchQueueProtobufClient) callDeleteJobGroup(ctx context.Context, in *DeleteJobGroupRequest) (*DeleteJobGroupResponse, error) { + out := new(DeleteJobGroupResponse) + ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[9], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +func (c *agentDispatchQueueProtobufClient) GetDispatchQueueConfig(ctx context.Context, in *GetDispatchQueueConfigRequest) (*GetDispatchQueueConfigResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentDispatchQueue") + ctx = ctxsetters.WithMethodName(ctx, "GetDispatchQueueConfig") + caller := c.callGetDispatchQueueConfig + if c.interceptor != nil { + caller = func(ctx context.Context, req *GetDispatchQueueConfigRequest) (*GetDispatchQueueConfigResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*GetDispatchQueueConfigRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*GetDispatchQueueConfigRequest) when calling interceptor") + } + return c.callGetDispatchQueueConfig(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*GetDispatchQueueConfigResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*GetDispatchQueueConfigResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentDispatchQueueProtobufClient) callGetDispatchQueueConfig(ctx context.Context, in *GetDispatchQueueConfigRequest) (*GetDispatchQueueConfigResponse, error) { + out := new(GetDispatchQueueConfigResponse) + ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[10], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +func (c *agentDispatchQueueProtobufClient) UpdateDispatchQueueConfig(ctx context.Context, in *UpdateDispatchQueueConfigRequest) (*UpdateDispatchQueueConfigResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentDispatchQueue") + ctx = ctxsetters.WithMethodName(ctx, "UpdateDispatchQueueConfig") + caller := c.callUpdateDispatchQueueConfig + if c.interceptor != nil { + caller = func(ctx context.Context, req *UpdateDispatchQueueConfigRequest) (*UpdateDispatchQueueConfigResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*UpdateDispatchQueueConfigRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*UpdateDispatchQueueConfigRequest) when calling interceptor") + } + return c.callUpdateDispatchQueueConfig(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*UpdateDispatchQueueConfigResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*UpdateDispatchQueueConfigResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentDispatchQueueProtobufClient) callUpdateDispatchQueueConfig(ctx context.Context, in *UpdateDispatchQueueConfigRequest) (*UpdateDispatchQueueConfigResponse, error) { + out := new(UpdateDispatchQueueConfigResponse) + ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[11], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +// ============================== +// AgentDispatchQueue JSON Client +// ============================== + +type agentDispatchQueueJSONClient struct { + client HTTPClient + urls [12]string + interceptor twirp.Interceptor + opts twirp.ClientOptions +} + +// NewAgentDispatchQueueJSONClient creates a JSON client that implements the AgentDispatchQueue interface. +// It communicates using JSON and can be configured with a custom HTTPClient. +func NewAgentDispatchQueueJSONClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) AgentDispatchQueue { + if c, ok := client.(*http.Client); ok { + client = withoutRedirects(c) + } + + clientOpts := twirp.ClientOptions{} + for _, o := range opts { + o(&clientOpts) + } + + // Using ReadOpt allows backwards and forwards compatibility with new options in the future + literalURLs := false + _ = clientOpts.ReadOpt("literalURLs", &literalURLs) + var pathPrefix string + if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { + pathPrefix = "/twirp" // default prefix + } + + // Build method URLs: []/./ + serviceURL := sanitizeBaseURL(baseURL) + serviceURL += baseServicePath(pathPrefix, "livekit", "AgentDispatchQueue") + urls := [12]string{ + serviceURL + "AddJobs", + serviceURL + "GetJob", + serviceURL + "ListJobs", + serviceURL + "RemoveJob", + serviceURL + "RetryJobs", + serviceURL + "ListJobGroups", + serviceURL + "PauseJobGroup", + serviceURL + "ResumeJobGroup", + serviceURL + "CancelJobGroup", + serviceURL + "DeleteJobGroup", + serviceURL + "GetDispatchQueueConfig", + serviceURL + "UpdateDispatchQueueConfig", + } + + return &agentDispatchQueueJSONClient{ + client: client, + urls: urls, + interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), + opts: clientOpts, + } +} + +func (c *agentDispatchQueueJSONClient) AddJobs(ctx context.Context, in *AddJobsRequest) (*AddJobsResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentDispatchQueue") + ctx = ctxsetters.WithMethodName(ctx, "AddJobs") + caller := c.callAddJobs + if c.interceptor != nil { + caller = func(ctx context.Context, req *AddJobsRequest) (*AddJobsResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*AddJobsRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*AddJobsRequest) when calling interceptor") + } + return c.callAddJobs(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*AddJobsResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*AddJobsResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentDispatchQueueJSONClient) callAddJobs(ctx context.Context, in *AddJobsRequest) (*AddJobsResponse, error) { + out := new(AddJobsResponse) + ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +func (c *agentDispatchQueueJSONClient) GetJob(ctx context.Context, in *GetJobRequest) (*GetJobResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentDispatchQueue") + ctx = ctxsetters.WithMethodName(ctx, "GetJob") + caller := c.callGetJob + if c.interceptor != nil { + caller = func(ctx context.Context, req *GetJobRequest) (*GetJobResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*GetJobRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*GetJobRequest) when calling interceptor") + } + return c.callGetJob(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*GetJobResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*GetJobResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentDispatchQueueJSONClient) callGetJob(ctx context.Context, in *GetJobRequest) (*GetJobResponse, error) { + out := new(GetJobResponse) + ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[1], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +func (c *agentDispatchQueueJSONClient) ListJobs(ctx context.Context, in *ListJobsRequest) (*ListJobsResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentDispatchQueue") + ctx = ctxsetters.WithMethodName(ctx, "ListJobs") + caller := c.callListJobs + if c.interceptor != nil { + caller = func(ctx context.Context, req *ListJobsRequest) (*ListJobsResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*ListJobsRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*ListJobsRequest) when calling interceptor") + } + return c.callListJobs(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*ListJobsResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*ListJobsResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentDispatchQueueJSONClient) callListJobs(ctx context.Context, in *ListJobsRequest) (*ListJobsResponse, error) { + out := new(ListJobsResponse) + ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[2], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +func (c *agentDispatchQueueJSONClient) RemoveJob(ctx context.Context, in *RemoveJobRequest) (*RemoveJobResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentDispatchQueue") + ctx = ctxsetters.WithMethodName(ctx, "RemoveJob") + caller := c.callRemoveJob + if c.interceptor != nil { + caller = func(ctx context.Context, req *RemoveJobRequest) (*RemoveJobResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*RemoveJobRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*RemoveJobRequest) when calling interceptor") + } + return c.callRemoveJob(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*RemoveJobResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*RemoveJobResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentDispatchQueueJSONClient) callRemoveJob(ctx context.Context, in *RemoveJobRequest) (*RemoveJobResponse, error) { + out := new(RemoveJobResponse) + ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[3], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +func (c *agentDispatchQueueJSONClient) RetryJobs(ctx context.Context, in *RetryJobsRequest) (*RetryJobsResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentDispatchQueue") + ctx = ctxsetters.WithMethodName(ctx, "RetryJobs") + caller := c.callRetryJobs + if c.interceptor != nil { + caller = func(ctx context.Context, req *RetryJobsRequest) (*RetryJobsResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*RetryJobsRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*RetryJobsRequest) when calling interceptor") + } + return c.callRetryJobs(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*RetryJobsResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*RetryJobsResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentDispatchQueueJSONClient) callRetryJobs(ctx context.Context, in *RetryJobsRequest) (*RetryJobsResponse, error) { + out := new(RetryJobsResponse) + ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[4], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +func (c *agentDispatchQueueJSONClient) ListJobGroups(ctx context.Context, in *ListJobGroupsRequest) (*ListJobGroupsResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentDispatchQueue") + ctx = ctxsetters.WithMethodName(ctx, "ListJobGroups") + caller := c.callListJobGroups + if c.interceptor != nil { + caller = func(ctx context.Context, req *ListJobGroupsRequest) (*ListJobGroupsResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*ListJobGroupsRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*ListJobGroupsRequest) when calling interceptor") + } + return c.callListJobGroups(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*ListJobGroupsResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*ListJobGroupsResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentDispatchQueueJSONClient) callListJobGroups(ctx context.Context, in *ListJobGroupsRequest) (*ListJobGroupsResponse, error) { + out := new(ListJobGroupsResponse) + ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[5], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +func (c *agentDispatchQueueJSONClient) PauseJobGroup(ctx context.Context, in *PauseJobGroupRequest) (*PauseJobGroupResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentDispatchQueue") + ctx = ctxsetters.WithMethodName(ctx, "PauseJobGroup") + caller := c.callPauseJobGroup + if c.interceptor != nil { + caller = func(ctx context.Context, req *PauseJobGroupRequest) (*PauseJobGroupResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*PauseJobGroupRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*PauseJobGroupRequest) when calling interceptor") + } + return c.callPauseJobGroup(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*PauseJobGroupResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*PauseJobGroupResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentDispatchQueueJSONClient) callPauseJobGroup(ctx context.Context, in *PauseJobGroupRequest) (*PauseJobGroupResponse, error) { + out := new(PauseJobGroupResponse) + ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[6], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +func (c *agentDispatchQueueJSONClient) ResumeJobGroup(ctx context.Context, in *ResumeJobGroupRequest) (*ResumeJobGroupResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentDispatchQueue") + ctx = ctxsetters.WithMethodName(ctx, "ResumeJobGroup") + caller := c.callResumeJobGroup + if c.interceptor != nil { + caller = func(ctx context.Context, req *ResumeJobGroupRequest) (*ResumeJobGroupResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*ResumeJobGroupRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*ResumeJobGroupRequest) when calling interceptor") + } + return c.callResumeJobGroup(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*ResumeJobGroupResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*ResumeJobGroupResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentDispatchQueueJSONClient) callResumeJobGroup(ctx context.Context, in *ResumeJobGroupRequest) (*ResumeJobGroupResponse, error) { + out := new(ResumeJobGroupResponse) + ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[7], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +func (c *agentDispatchQueueJSONClient) CancelJobGroup(ctx context.Context, in *CancelJobGroupRequest) (*CancelJobGroupResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentDispatchQueue") + ctx = ctxsetters.WithMethodName(ctx, "CancelJobGroup") + caller := c.callCancelJobGroup + if c.interceptor != nil { + caller = func(ctx context.Context, req *CancelJobGroupRequest) (*CancelJobGroupResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*CancelJobGroupRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*CancelJobGroupRequest) when calling interceptor") + } + return c.callCancelJobGroup(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*CancelJobGroupResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*CancelJobGroupResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentDispatchQueueJSONClient) callCancelJobGroup(ctx context.Context, in *CancelJobGroupRequest) (*CancelJobGroupResponse, error) { + out := new(CancelJobGroupResponse) + ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[8], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +func (c *agentDispatchQueueJSONClient) DeleteJobGroup(ctx context.Context, in *DeleteJobGroupRequest) (*DeleteJobGroupResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentDispatchQueue") + ctx = ctxsetters.WithMethodName(ctx, "DeleteJobGroup") + caller := c.callDeleteJobGroup + if c.interceptor != nil { + caller = func(ctx context.Context, req *DeleteJobGroupRequest) (*DeleteJobGroupResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*DeleteJobGroupRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*DeleteJobGroupRequest) when calling interceptor") + } + return c.callDeleteJobGroup(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*DeleteJobGroupResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*DeleteJobGroupResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentDispatchQueueJSONClient) callDeleteJobGroup(ctx context.Context, in *DeleteJobGroupRequest) (*DeleteJobGroupResponse, error) { + out := new(DeleteJobGroupResponse) + ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[9], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +func (c *agentDispatchQueueJSONClient) GetDispatchQueueConfig(ctx context.Context, in *GetDispatchQueueConfigRequest) (*GetDispatchQueueConfigResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentDispatchQueue") + ctx = ctxsetters.WithMethodName(ctx, "GetDispatchQueueConfig") + caller := c.callGetDispatchQueueConfig + if c.interceptor != nil { + caller = func(ctx context.Context, req *GetDispatchQueueConfigRequest) (*GetDispatchQueueConfigResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*GetDispatchQueueConfigRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*GetDispatchQueueConfigRequest) when calling interceptor") + } + return c.callGetDispatchQueueConfig(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*GetDispatchQueueConfigResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*GetDispatchQueueConfigResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentDispatchQueueJSONClient) callGetDispatchQueueConfig(ctx context.Context, in *GetDispatchQueueConfigRequest) (*GetDispatchQueueConfigResponse, error) { + out := new(GetDispatchQueueConfigResponse) + ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[10], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +func (c *agentDispatchQueueJSONClient) UpdateDispatchQueueConfig(ctx context.Context, in *UpdateDispatchQueueConfigRequest) (*UpdateDispatchQueueConfigResponse, error) { + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentDispatchQueue") + ctx = ctxsetters.WithMethodName(ctx, "UpdateDispatchQueueConfig") + caller := c.callUpdateDispatchQueueConfig + if c.interceptor != nil { + caller = func(ctx context.Context, req *UpdateDispatchQueueConfigRequest) (*UpdateDispatchQueueConfigResponse, error) { + resp, err := c.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*UpdateDispatchQueueConfigRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*UpdateDispatchQueueConfigRequest) when calling interceptor") + } + return c.callUpdateDispatchQueueConfig(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*UpdateDispatchQueueConfigResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*UpdateDispatchQueueConfigResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + return caller(ctx, in) +} + +func (c *agentDispatchQueueJSONClient) callUpdateDispatchQueueConfig(ctx context.Context, in *UpdateDispatchQueueConfigRequest) (*UpdateDispatchQueueConfigResponse, error) { + out := new(UpdateDispatchQueueConfigResponse) + ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[11], in, out) + if err != nil { + twerr, ok := err.(twirp.Error) + if !ok { + twerr = twirp.InternalErrorWith(err) + } + callClientError(ctx, c.opts.Hooks, twerr) + return nil, err + } + + callClientResponseReceived(ctx, c.opts.Hooks) + + return out, nil +} + +// ================================= +// AgentDispatchQueue Server Handler +// ================================= + +type agentDispatchQueueServer struct { + AgentDispatchQueue + interceptor twirp.Interceptor + hooks *twirp.ServerHooks + pathPrefix string // prefix for routing + jsonSkipDefaults bool // do not include unpopulated fields (default values) in the response + jsonCamelCase bool // JSON fields are serialized as lowerCamelCase rather than keeping the original proto names +} + +// NewAgentDispatchQueueServer builds a TwirpServer that can be used as an http.Handler to handle +// HTTP requests that are routed to the right method in the provided svc implementation. +// The opts are twirp.ServerOption modifiers, for example twirp.WithServerHooks(hooks). +func NewAgentDispatchQueueServer(svc AgentDispatchQueue, opts ...interface{}) TwirpServer { + serverOpts := newServerOpts(opts) + + // Using ReadOpt allows backwards and forwards compatibility with new options in the future + jsonSkipDefaults := false + _ = serverOpts.ReadOpt("jsonSkipDefaults", &jsonSkipDefaults) + jsonCamelCase := false + _ = serverOpts.ReadOpt("jsonCamelCase", &jsonCamelCase) + var pathPrefix string + if ok := serverOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { + pathPrefix = "/twirp" // default prefix + } + + return &agentDispatchQueueServer{ + AgentDispatchQueue: svc, + hooks: serverOpts.Hooks, + interceptor: twirp.ChainInterceptors(serverOpts.Interceptors...), + pathPrefix: pathPrefix, + jsonSkipDefaults: jsonSkipDefaults, + jsonCamelCase: jsonCamelCase, + } +} + +// writeError writes an HTTP response with a valid Twirp error format, and triggers hooks. +// If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) +func (s *agentDispatchQueueServer) writeError(ctx context.Context, resp http.ResponseWriter, err error) { + writeError(ctx, resp, err, s.hooks) +} + +// handleRequestBodyError is used to handle error when the twirp server cannot read request +func (s *agentDispatchQueueServer) handleRequestBodyError(ctx context.Context, resp http.ResponseWriter, msg string, err error) { + if context.Canceled == ctx.Err() { + s.writeError(ctx, resp, twirp.NewError(twirp.Canceled, "failed to read request: context canceled")) + return + } + if context.DeadlineExceeded == ctx.Err() { + s.writeError(ctx, resp, twirp.NewError(twirp.DeadlineExceeded, "failed to read request: deadline exceeded")) + return + } + s.writeError(ctx, resp, twirp.WrapError(malformedRequestError(msg), err)) +} + +// AgentDispatchQueuePathPrefix is a convenience constant that may identify URL paths. +// Should be used with caution, it only matches routes generated by Twirp Go clients, +// with the default "/twirp" prefix and default CamelCase service and method names. +// More info: https://twitchtv.github.io/twirp/docs/routing.html +const AgentDispatchQueuePathPrefix = "/twirp/livekit.AgentDispatchQueue/" + +func (s *agentDispatchQueueServer) ServeHTTP(resp http.ResponseWriter, req *http.Request) { + ctx := req.Context() + ctx = ctxsetters.WithPackageName(ctx, "livekit") + ctx = ctxsetters.WithServiceName(ctx, "AgentDispatchQueue") + ctx = ctxsetters.WithResponseWriter(ctx, resp) + + var err error + ctx, err = callRequestReceived(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + if req.Method != "POST" { + msg := fmt.Sprintf("unsupported method %q (only POST is allowed)", req.Method) + s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) + return + } + + // Verify path format: []/./ + prefix, pkgService, method := parseTwirpPath(req.URL.Path) + if pkgService != "livekit.AgentDispatchQueue" { + msg := fmt.Sprintf("no handler for path %q", req.URL.Path) + s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) + return + } + if prefix != s.pathPrefix { + msg := fmt.Sprintf("invalid path prefix %q, expected %q, on path %q", prefix, s.pathPrefix, req.URL.Path) + s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) + return + } + + switch method { + case "AddJobs": + s.serveAddJobs(ctx, resp, req) + return + case "GetJob": + s.serveGetJob(ctx, resp, req) + return + case "ListJobs": + s.serveListJobs(ctx, resp, req) + return + case "RemoveJob": + s.serveRemoveJob(ctx, resp, req) + return + case "RetryJobs": + s.serveRetryJobs(ctx, resp, req) + return + case "ListJobGroups": + s.serveListJobGroups(ctx, resp, req) + return + case "PauseJobGroup": + s.servePauseJobGroup(ctx, resp, req) + return + case "ResumeJobGroup": + s.serveResumeJobGroup(ctx, resp, req) + return + case "CancelJobGroup": + s.serveCancelJobGroup(ctx, resp, req) + return + case "DeleteJobGroup": + s.serveDeleteJobGroup(ctx, resp, req) + return + case "GetDispatchQueueConfig": + s.serveGetDispatchQueueConfig(ctx, resp, req) + return + case "UpdateDispatchQueueConfig": + s.serveUpdateDispatchQueueConfig(ctx, resp, req) + return + default: + msg := fmt.Sprintf("no handler for path %q", req.URL.Path) + s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) + return + } +} + +func (s *agentDispatchQueueServer) serveAddJobs(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + header := req.Header.Get("Content-Type") + i := strings.Index(header, ";") + if i == -1 { + i = len(header) + } + switch strings.TrimSpace(strings.ToLower(header[:i])) { + case "application/json": + s.serveAddJobsJSON(ctx, resp, req) + case "application/protobuf": + s.serveAddJobsProtobuf(ctx, resp, req) + default: + msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) + twerr := badRouteError(msg, req.Method, req.URL.Path) + s.writeError(ctx, resp, twerr) + } +} + +func (s *agentDispatchQueueServer) serveAddJobsJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "AddJobs") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + d := json.NewDecoder(req.Body) + rawReqBody := json.RawMessage{} + if err := d.Decode(&rawReqBody); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + reqContent := new(AddJobsRequest) + unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} + if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + + handler := s.AgentDispatchQueue.AddJobs + if s.interceptor != nil { + handler = func(ctx context.Context, req *AddJobsRequest) (*AddJobsResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*AddJobsRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*AddJobsRequest) when calling interceptor") + } + return s.AgentDispatchQueue.AddJobs(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*AddJobsResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*AddJobsResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *AddJobsResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *AddJobsResponse and nil error while calling AddJobs. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} + respBytes, err := marshaler.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/json") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentDispatchQueueServer) serveAddJobsProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "AddJobs") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + buf, err := io.ReadAll(req.Body) + if err != nil { + s.handleRequestBodyError(ctx, resp, "failed to read request body", err) + return + } + reqContent := new(AddJobsRequest) + if err = proto.Unmarshal(buf, reqContent); err != nil { + s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) + return + } + + handler := s.AgentDispatchQueue.AddJobs + if s.interceptor != nil { + handler = func(ctx context.Context, req *AddJobsRequest) (*AddJobsResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*AddJobsRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*AddJobsRequest) when calling interceptor") + } + return s.AgentDispatchQueue.AddJobs(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*AddJobsResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*AddJobsResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *AddJobsResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *AddJobsResponse and nil error while calling AddJobs. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + respBytes, err := proto.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/protobuf") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentDispatchQueueServer) serveGetJob(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + header := req.Header.Get("Content-Type") + i := strings.Index(header, ";") + if i == -1 { + i = len(header) + } + switch strings.TrimSpace(strings.ToLower(header[:i])) { + case "application/json": + s.serveGetJobJSON(ctx, resp, req) + case "application/protobuf": + s.serveGetJobProtobuf(ctx, resp, req) + default: + msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) + twerr := badRouteError(msg, req.Method, req.URL.Path) + s.writeError(ctx, resp, twerr) + } +} + +func (s *agentDispatchQueueServer) serveGetJobJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "GetJob") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + d := json.NewDecoder(req.Body) + rawReqBody := json.RawMessage{} + if err := d.Decode(&rawReqBody); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + reqContent := new(GetJobRequest) + unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} + if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + + handler := s.AgentDispatchQueue.GetJob + if s.interceptor != nil { + handler = func(ctx context.Context, req *GetJobRequest) (*GetJobResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*GetJobRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*GetJobRequest) when calling interceptor") + } + return s.AgentDispatchQueue.GetJob(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*GetJobResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*GetJobResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *GetJobResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *GetJobResponse and nil error while calling GetJob. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} + respBytes, err := marshaler.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/json") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentDispatchQueueServer) serveGetJobProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "GetJob") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + buf, err := io.ReadAll(req.Body) + if err != nil { + s.handleRequestBodyError(ctx, resp, "failed to read request body", err) + return + } + reqContent := new(GetJobRequest) + if err = proto.Unmarshal(buf, reqContent); err != nil { + s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) + return + } + + handler := s.AgentDispatchQueue.GetJob + if s.interceptor != nil { + handler = func(ctx context.Context, req *GetJobRequest) (*GetJobResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*GetJobRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*GetJobRequest) when calling interceptor") + } + return s.AgentDispatchQueue.GetJob(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*GetJobResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*GetJobResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *GetJobResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *GetJobResponse and nil error while calling GetJob. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + respBytes, err := proto.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/protobuf") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentDispatchQueueServer) serveListJobs(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + header := req.Header.Get("Content-Type") + i := strings.Index(header, ";") + if i == -1 { + i = len(header) + } + switch strings.TrimSpace(strings.ToLower(header[:i])) { + case "application/json": + s.serveListJobsJSON(ctx, resp, req) + case "application/protobuf": + s.serveListJobsProtobuf(ctx, resp, req) + default: + msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) + twerr := badRouteError(msg, req.Method, req.URL.Path) + s.writeError(ctx, resp, twerr) + } +} + +func (s *agentDispatchQueueServer) serveListJobsJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "ListJobs") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + d := json.NewDecoder(req.Body) + rawReqBody := json.RawMessage{} + if err := d.Decode(&rawReqBody); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + reqContent := new(ListJobsRequest) + unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} + if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + + handler := s.AgentDispatchQueue.ListJobs + if s.interceptor != nil { + handler = func(ctx context.Context, req *ListJobsRequest) (*ListJobsResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*ListJobsRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*ListJobsRequest) when calling interceptor") + } + return s.AgentDispatchQueue.ListJobs(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*ListJobsResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*ListJobsResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *ListJobsResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *ListJobsResponse and nil error while calling ListJobs. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} + respBytes, err := marshaler.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/json") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentDispatchQueueServer) serveListJobsProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "ListJobs") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + buf, err := io.ReadAll(req.Body) + if err != nil { + s.handleRequestBodyError(ctx, resp, "failed to read request body", err) + return + } + reqContent := new(ListJobsRequest) + if err = proto.Unmarshal(buf, reqContent); err != nil { + s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) + return + } + + handler := s.AgentDispatchQueue.ListJobs + if s.interceptor != nil { + handler = func(ctx context.Context, req *ListJobsRequest) (*ListJobsResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*ListJobsRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*ListJobsRequest) when calling interceptor") + } + return s.AgentDispatchQueue.ListJobs(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*ListJobsResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*ListJobsResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *ListJobsResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *ListJobsResponse and nil error while calling ListJobs. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + respBytes, err := proto.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/protobuf") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentDispatchQueueServer) serveRemoveJob(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + header := req.Header.Get("Content-Type") + i := strings.Index(header, ";") + if i == -1 { + i = len(header) + } + switch strings.TrimSpace(strings.ToLower(header[:i])) { + case "application/json": + s.serveRemoveJobJSON(ctx, resp, req) + case "application/protobuf": + s.serveRemoveJobProtobuf(ctx, resp, req) + default: + msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) + twerr := badRouteError(msg, req.Method, req.URL.Path) + s.writeError(ctx, resp, twerr) + } +} + +func (s *agentDispatchQueueServer) serveRemoveJobJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "RemoveJob") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + d := json.NewDecoder(req.Body) + rawReqBody := json.RawMessage{} + if err := d.Decode(&rawReqBody); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + reqContent := new(RemoveJobRequest) + unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} + if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + + handler := s.AgentDispatchQueue.RemoveJob + if s.interceptor != nil { + handler = func(ctx context.Context, req *RemoveJobRequest) (*RemoveJobResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*RemoveJobRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*RemoveJobRequest) when calling interceptor") + } + return s.AgentDispatchQueue.RemoveJob(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*RemoveJobResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*RemoveJobResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *RemoveJobResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *RemoveJobResponse and nil error while calling RemoveJob. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} + respBytes, err := marshaler.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/json") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentDispatchQueueServer) serveRemoveJobProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "RemoveJob") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + buf, err := io.ReadAll(req.Body) + if err != nil { + s.handleRequestBodyError(ctx, resp, "failed to read request body", err) + return + } + reqContent := new(RemoveJobRequest) + if err = proto.Unmarshal(buf, reqContent); err != nil { + s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) + return + } + + handler := s.AgentDispatchQueue.RemoveJob + if s.interceptor != nil { + handler = func(ctx context.Context, req *RemoveJobRequest) (*RemoveJobResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*RemoveJobRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*RemoveJobRequest) when calling interceptor") + } + return s.AgentDispatchQueue.RemoveJob(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*RemoveJobResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*RemoveJobResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *RemoveJobResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *RemoveJobResponse and nil error while calling RemoveJob. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + respBytes, err := proto.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/protobuf") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentDispatchQueueServer) serveRetryJobs(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + header := req.Header.Get("Content-Type") + i := strings.Index(header, ";") + if i == -1 { + i = len(header) + } + switch strings.TrimSpace(strings.ToLower(header[:i])) { + case "application/json": + s.serveRetryJobsJSON(ctx, resp, req) + case "application/protobuf": + s.serveRetryJobsProtobuf(ctx, resp, req) + default: + msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) + twerr := badRouteError(msg, req.Method, req.URL.Path) + s.writeError(ctx, resp, twerr) + } +} + +func (s *agentDispatchQueueServer) serveRetryJobsJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "RetryJobs") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + d := json.NewDecoder(req.Body) + rawReqBody := json.RawMessage{} + if err := d.Decode(&rawReqBody); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + reqContent := new(RetryJobsRequest) + unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} + if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + + handler := s.AgentDispatchQueue.RetryJobs + if s.interceptor != nil { + handler = func(ctx context.Context, req *RetryJobsRequest) (*RetryJobsResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*RetryJobsRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*RetryJobsRequest) when calling interceptor") + } + return s.AgentDispatchQueue.RetryJobs(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*RetryJobsResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*RetryJobsResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *RetryJobsResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *RetryJobsResponse and nil error while calling RetryJobs. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} + respBytes, err := marshaler.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/json") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentDispatchQueueServer) serveRetryJobsProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "RetryJobs") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + buf, err := io.ReadAll(req.Body) + if err != nil { + s.handleRequestBodyError(ctx, resp, "failed to read request body", err) + return + } + reqContent := new(RetryJobsRequest) + if err = proto.Unmarshal(buf, reqContent); err != nil { + s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) + return + } + + handler := s.AgentDispatchQueue.RetryJobs + if s.interceptor != nil { + handler = func(ctx context.Context, req *RetryJobsRequest) (*RetryJobsResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*RetryJobsRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*RetryJobsRequest) when calling interceptor") + } + return s.AgentDispatchQueue.RetryJobs(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*RetryJobsResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*RetryJobsResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *RetryJobsResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *RetryJobsResponse and nil error while calling RetryJobs. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + respBytes, err := proto.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/protobuf") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentDispatchQueueServer) serveListJobGroups(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + header := req.Header.Get("Content-Type") + i := strings.Index(header, ";") + if i == -1 { + i = len(header) + } + switch strings.TrimSpace(strings.ToLower(header[:i])) { + case "application/json": + s.serveListJobGroupsJSON(ctx, resp, req) + case "application/protobuf": + s.serveListJobGroupsProtobuf(ctx, resp, req) + default: + msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) + twerr := badRouteError(msg, req.Method, req.URL.Path) + s.writeError(ctx, resp, twerr) + } +} + +func (s *agentDispatchQueueServer) serveListJobGroupsJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "ListJobGroups") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + d := json.NewDecoder(req.Body) + rawReqBody := json.RawMessage{} + if err := d.Decode(&rawReqBody); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + reqContent := new(ListJobGroupsRequest) + unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} + if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + + handler := s.AgentDispatchQueue.ListJobGroups + if s.interceptor != nil { + handler = func(ctx context.Context, req *ListJobGroupsRequest) (*ListJobGroupsResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*ListJobGroupsRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*ListJobGroupsRequest) when calling interceptor") + } + return s.AgentDispatchQueue.ListJobGroups(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*ListJobGroupsResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*ListJobGroupsResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *ListJobGroupsResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *ListJobGroupsResponse and nil error while calling ListJobGroups. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} + respBytes, err := marshaler.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/json") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentDispatchQueueServer) serveListJobGroupsProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "ListJobGroups") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + buf, err := io.ReadAll(req.Body) + if err != nil { + s.handleRequestBodyError(ctx, resp, "failed to read request body", err) + return + } + reqContent := new(ListJobGroupsRequest) + if err = proto.Unmarshal(buf, reqContent); err != nil { + s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) + return + } + + handler := s.AgentDispatchQueue.ListJobGroups + if s.interceptor != nil { + handler = func(ctx context.Context, req *ListJobGroupsRequest) (*ListJobGroupsResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*ListJobGroupsRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*ListJobGroupsRequest) when calling interceptor") + } + return s.AgentDispatchQueue.ListJobGroups(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*ListJobGroupsResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*ListJobGroupsResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *ListJobGroupsResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *ListJobGroupsResponse and nil error while calling ListJobGroups. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + respBytes, err := proto.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/protobuf") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentDispatchQueueServer) servePauseJobGroup(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + header := req.Header.Get("Content-Type") + i := strings.Index(header, ";") + if i == -1 { + i = len(header) + } + switch strings.TrimSpace(strings.ToLower(header[:i])) { + case "application/json": + s.servePauseJobGroupJSON(ctx, resp, req) + case "application/protobuf": + s.servePauseJobGroupProtobuf(ctx, resp, req) + default: + msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) + twerr := badRouteError(msg, req.Method, req.URL.Path) + s.writeError(ctx, resp, twerr) + } +} + +func (s *agentDispatchQueueServer) servePauseJobGroupJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "PauseJobGroup") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + d := json.NewDecoder(req.Body) + rawReqBody := json.RawMessage{} + if err := d.Decode(&rawReqBody); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + reqContent := new(PauseJobGroupRequest) + unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} + if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + + handler := s.AgentDispatchQueue.PauseJobGroup + if s.interceptor != nil { + handler = func(ctx context.Context, req *PauseJobGroupRequest) (*PauseJobGroupResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*PauseJobGroupRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*PauseJobGroupRequest) when calling interceptor") + } + return s.AgentDispatchQueue.PauseJobGroup(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*PauseJobGroupResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*PauseJobGroupResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *PauseJobGroupResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *PauseJobGroupResponse and nil error while calling PauseJobGroup. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} + respBytes, err := marshaler.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/json") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentDispatchQueueServer) servePauseJobGroupProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "PauseJobGroup") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + buf, err := io.ReadAll(req.Body) + if err != nil { + s.handleRequestBodyError(ctx, resp, "failed to read request body", err) + return + } + reqContent := new(PauseJobGroupRequest) + if err = proto.Unmarshal(buf, reqContent); err != nil { + s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) + return + } + + handler := s.AgentDispatchQueue.PauseJobGroup + if s.interceptor != nil { + handler = func(ctx context.Context, req *PauseJobGroupRequest) (*PauseJobGroupResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*PauseJobGroupRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*PauseJobGroupRequest) when calling interceptor") + } + return s.AgentDispatchQueue.PauseJobGroup(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*PauseJobGroupResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*PauseJobGroupResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *PauseJobGroupResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *PauseJobGroupResponse and nil error while calling PauseJobGroup. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + respBytes, err := proto.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/protobuf") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentDispatchQueueServer) serveResumeJobGroup(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + header := req.Header.Get("Content-Type") + i := strings.Index(header, ";") + if i == -1 { + i = len(header) + } + switch strings.TrimSpace(strings.ToLower(header[:i])) { + case "application/json": + s.serveResumeJobGroupJSON(ctx, resp, req) + case "application/protobuf": + s.serveResumeJobGroupProtobuf(ctx, resp, req) + default: + msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) + twerr := badRouteError(msg, req.Method, req.URL.Path) + s.writeError(ctx, resp, twerr) + } +} + +func (s *agentDispatchQueueServer) serveResumeJobGroupJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "ResumeJobGroup") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + d := json.NewDecoder(req.Body) + rawReqBody := json.RawMessage{} + if err := d.Decode(&rawReqBody); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + reqContent := new(ResumeJobGroupRequest) + unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} + if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + + handler := s.AgentDispatchQueue.ResumeJobGroup + if s.interceptor != nil { + handler = func(ctx context.Context, req *ResumeJobGroupRequest) (*ResumeJobGroupResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*ResumeJobGroupRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*ResumeJobGroupRequest) when calling interceptor") + } + return s.AgentDispatchQueue.ResumeJobGroup(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*ResumeJobGroupResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*ResumeJobGroupResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *ResumeJobGroupResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *ResumeJobGroupResponse and nil error while calling ResumeJobGroup. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} + respBytes, err := marshaler.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/json") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentDispatchQueueServer) serveResumeJobGroupProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "ResumeJobGroup") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + buf, err := io.ReadAll(req.Body) + if err != nil { + s.handleRequestBodyError(ctx, resp, "failed to read request body", err) + return + } + reqContent := new(ResumeJobGroupRequest) + if err = proto.Unmarshal(buf, reqContent); err != nil { + s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) + return + } + + handler := s.AgentDispatchQueue.ResumeJobGroup + if s.interceptor != nil { + handler = func(ctx context.Context, req *ResumeJobGroupRequest) (*ResumeJobGroupResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*ResumeJobGroupRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*ResumeJobGroupRequest) when calling interceptor") + } + return s.AgentDispatchQueue.ResumeJobGroup(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*ResumeJobGroupResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*ResumeJobGroupResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *ResumeJobGroupResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *ResumeJobGroupResponse and nil error while calling ResumeJobGroup. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + respBytes, err := proto.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/protobuf") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentDispatchQueueServer) serveCancelJobGroup(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + header := req.Header.Get("Content-Type") + i := strings.Index(header, ";") + if i == -1 { + i = len(header) + } + switch strings.TrimSpace(strings.ToLower(header[:i])) { + case "application/json": + s.serveCancelJobGroupJSON(ctx, resp, req) + case "application/protobuf": + s.serveCancelJobGroupProtobuf(ctx, resp, req) + default: + msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) + twerr := badRouteError(msg, req.Method, req.URL.Path) + s.writeError(ctx, resp, twerr) + } +} + +func (s *agentDispatchQueueServer) serveCancelJobGroupJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "CancelJobGroup") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + d := json.NewDecoder(req.Body) + rawReqBody := json.RawMessage{} + if err := d.Decode(&rawReqBody); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + reqContent := new(CancelJobGroupRequest) + unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} + if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + + handler := s.AgentDispatchQueue.CancelJobGroup + if s.interceptor != nil { + handler = func(ctx context.Context, req *CancelJobGroupRequest) (*CancelJobGroupResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*CancelJobGroupRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*CancelJobGroupRequest) when calling interceptor") + } + return s.AgentDispatchQueue.CancelJobGroup(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*CancelJobGroupResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*CancelJobGroupResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *CancelJobGroupResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *CancelJobGroupResponse and nil error while calling CancelJobGroup. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} + respBytes, err := marshaler.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/json") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentDispatchQueueServer) serveCancelJobGroupProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "CancelJobGroup") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + buf, err := io.ReadAll(req.Body) + if err != nil { + s.handleRequestBodyError(ctx, resp, "failed to read request body", err) + return + } + reqContent := new(CancelJobGroupRequest) + if err = proto.Unmarshal(buf, reqContent); err != nil { + s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) + return + } + + handler := s.AgentDispatchQueue.CancelJobGroup + if s.interceptor != nil { + handler = func(ctx context.Context, req *CancelJobGroupRequest) (*CancelJobGroupResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*CancelJobGroupRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*CancelJobGroupRequest) when calling interceptor") + } + return s.AgentDispatchQueue.CancelJobGroup(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*CancelJobGroupResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*CancelJobGroupResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *CancelJobGroupResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *CancelJobGroupResponse and nil error while calling CancelJobGroup. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + respBytes, err := proto.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/protobuf") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentDispatchQueueServer) serveDeleteJobGroup(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + header := req.Header.Get("Content-Type") + i := strings.Index(header, ";") + if i == -1 { + i = len(header) + } + switch strings.TrimSpace(strings.ToLower(header[:i])) { + case "application/json": + s.serveDeleteJobGroupJSON(ctx, resp, req) + case "application/protobuf": + s.serveDeleteJobGroupProtobuf(ctx, resp, req) + default: + msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) + twerr := badRouteError(msg, req.Method, req.URL.Path) + s.writeError(ctx, resp, twerr) + } +} + +func (s *agentDispatchQueueServer) serveDeleteJobGroupJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "DeleteJobGroup") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + d := json.NewDecoder(req.Body) + rawReqBody := json.RawMessage{} + if err := d.Decode(&rawReqBody); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + reqContent := new(DeleteJobGroupRequest) + unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} + if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + + handler := s.AgentDispatchQueue.DeleteJobGroup + if s.interceptor != nil { + handler = func(ctx context.Context, req *DeleteJobGroupRequest) (*DeleteJobGroupResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*DeleteJobGroupRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*DeleteJobGroupRequest) when calling interceptor") + } + return s.AgentDispatchQueue.DeleteJobGroup(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*DeleteJobGroupResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*DeleteJobGroupResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *DeleteJobGroupResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *DeleteJobGroupResponse and nil error while calling DeleteJobGroup. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} + respBytes, err := marshaler.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/json") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentDispatchQueueServer) serveDeleteJobGroupProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "DeleteJobGroup") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + buf, err := io.ReadAll(req.Body) + if err != nil { + s.handleRequestBodyError(ctx, resp, "failed to read request body", err) + return + } + reqContent := new(DeleteJobGroupRequest) + if err = proto.Unmarshal(buf, reqContent); err != nil { + s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) + return + } + + handler := s.AgentDispatchQueue.DeleteJobGroup + if s.interceptor != nil { + handler = func(ctx context.Context, req *DeleteJobGroupRequest) (*DeleteJobGroupResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*DeleteJobGroupRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*DeleteJobGroupRequest) when calling interceptor") + } + return s.AgentDispatchQueue.DeleteJobGroup(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*DeleteJobGroupResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*DeleteJobGroupResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *DeleteJobGroupResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *DeleteJobGroupResponse and nil error while calling DeleteJobGroup. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + respBytes, err := proto.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/protobuf") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentDispatchQueueServer) serveGetDispatchQueueConfig(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + header := req.Header.Get("Content-Type") + i := strings.Index(header, ";") + if i == -1 { + i = len(header) + } + switch strings.TrimSpace(strings.ToLower(header[:i])) { + case "application/json": + s.serveGetDispatchQueueConfigJSON(ctx, resp, req) + case "application/protobuf": + s.serveGetDispatchQueueConfigProtobuf(ctx, resp, req) + default: + msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) + twerr := badRouteError(msg, req.Method, req.URL.Path) + s.writeError(ctx, resp, twerr) + } +} + +func (s *agentDispatchQueueServer) serveGetDispatchQueueConfigJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "GetDispatchQueueConfig") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + d := json.NewDecoder(req.Body) + rawReqBody := json.RawMessage{} + if err := d.Decode(&rawReqBody); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + reqContent := new(GetDispatchQueueConfigRequest) + unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} + if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + + handler := s.AgentDispatchQueue.GetDispatchQueueConfig + if s.interceptor != nil { + handler = func(ctx context.Context, req *GetDispatchQueueConfigRequest) (*GetDispatchQueueConfigResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*GetDispatchQueueConfigRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*GetDispatchQueueConfigRequest) when calling interceptor") + } + return s.AgentDispatchQueue.GetDispatchQueueConfig(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*GetDispatchQueueConfigResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*GetDispatchQueueConfigResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *GetDispatchQueueConfigResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *GetDispatchQueueConfigResponse and nil error while calling GetDispatchQueueConfig. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} + respBytes, err := marshaler.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/json") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentDispatchQueueServer) serveGetDispatchQueueConfigProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "GetDispatchQueueConfig") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + buf, err := io.ReadAll(req.Body) + if err != nil { + s.handleRequestBodyError(ctx, resp, "failed to read request body", err) + return + } + reqContent := new(GetDispatchQueueConfigRequest) + if err = proto.Unmarshal(buf, reqContent); err != nil { + s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) + return + } + + handler := s.AgentDispatchQueue.GetDispatchQueueConfig + if s.interceptor != nil { + handler = func(ctx context.Context, req *GetDispatchQueueConfigRequest) (*GetDispatchQueueConfigResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*GetDispatchQueueConfigRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*GetDispatchQueueConfigRequest) when calling interceptor") + } + return s.AgentDispatchQueue.GetDispatchQueueConfig(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*GetDispatchQueueConfigResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*GetDispatchQueueConfigResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *GetDispatchQueueConfigResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *GetDispatchQueueConfigResponse and nil error while calling GetDispatchQueueConfig. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + respBytes, err := proto.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/protobuf") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentDispatchQueueServer) serveUpdateDispatchQueueConfig(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + header := req.Header.Get("Content-Type") + i := strings.Index(header, ";") + if i == -1 { + i = len(header) + } + switch strings.TrimSpace(strings.ToLower(header[:i])) { + case "application/json": + s.serveUpdateDispatchQueueConfigJSON(ctx, resp, req) + case "application/protobuf": + s.serveUpdateDispatchQueueConfigProtobuf(ctx, resp, req) + default: + msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) + twerr := badRouteError(msg, req.Method, req.URL.Path) + s.writeError(ctx, resp, twerr) + } +} + +func (s *agentDispatchQueueServer) serveUpdateDispatchQueueConfigJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "UpdateDispatchQueueConfig") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + d := json.NewDecoder(req.Body) + rawReqBody := json.RawMessage{} + if err := d.Decode(&rawReqBody); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + reqContent := new(UpdateDispatchQueueConfigRequest) + unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} + if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { + s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) + return + } + + handler := s.AgentDispatchQueue.UpdateDispatchQueueConfig + if s.interceptor != nil { + handler = func(ctx context.Context, req *UpdateDispatchQueueConfigRequest) (*UpdateDispatchQueueConfigResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*UpdateDispatchQueueConfigRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*UpdateDispatchQueueConfigRequest) when calling interceptor") + } + return s.AgentDispatchQueue.UpdateDispatchQueueConfig(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*UpdateDispatchQueueConfigResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*UpdateDispatchQueueConfigResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *UpdateDispatchQueueConfigResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *UpdateDispatchQueueConfigResponse and nil error while calling UpdateDispatchQueueConfig. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} + respBytes, err := marshaler.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/json") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentDispatchQueueServer) serveUpdateDispatchQueueConfigProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { + var err error + ctx = ctxsetters.WithMethodName(ctx, "UpdateDispatchQueueConfig") + ctx, err = callRequestRouted(ctx, s.hooks) + if err != nil { + s.writeError(ctx, resp, err) + return + } + + buf, err := io.ReadAll(req.Body) + if err != nil { + s.handleRequestBodyError(ctx, resp, "failed to read request body", err) + return + } + reqContent := new(UpdateDispatchQueueConfigRequest) + if err = proto.Unmarshal(buf, reqContent); err != nil { + s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) + return + } + + handler := s.AgentDispatchQueue.UpdateDispatchQueueConfig + if s.interceptor != nil { + handler = func(ctx context.Context, req *UpdateDispatchQueueConfigRequest) (*UpdateDispatchQueueConfigResponse, error) { + resp, err := s.interceptor( + func(ctx context.Context, req interface{}) (interface{}, error) { + typedReq, ok := req.(*UpdateDispatchQueueConfigRequest) + if !ok { + return nil, twirp.InternalError("failed type assertion req.(*UpdateDispatchQueueConfigRequest) when calling interceptor") + } + return s.AgentDispatchQueue.UpdateDispatchQueueConfig(ctx, typedReq) + }, + )(ctx, req) + if resp != nil { + typedResp, ok := resp.(*UpdateDispatchQueueConfigResponse) + if !ok { + return nil, twirp.InternalError("failed type assertion resp.(*UpdateDispatchQueueConfigResponse) when calling interceptor") + } + return typedResp, err + } + return nil, err + } + } + + // Call service method + var respContent *UpdateDispatchQueueConfigResponse + func() { + defer ensurePanicResponses(ctx, resp, s.hooks) + respContent, err = handler(ctx, reqContent) + }() + + if err != nil { + s.writeError(ctx, resp, err) + return + } + if respContent == nil { + s.writeError(ctx, resp, twirp.InternalError("received a nil *UpdateDispatchQueueConfigResponse and nil error while calling UpdateDispatchQueueConfig. nil responses are not supported")) + return + } + + ctx = callResponsePrepared(ctx, s.hooks) + + respBytes, err := proto.Marshal(respContent) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) + return + } + + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) + resp.Header().Set("Content-Type", "application/protobuf") + resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) + resp.WriteHeader(http.StatusOK) + if n, err := resp.Write(respBytes); err != nil { + msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) + twerr := twirp.NewError(twirp.Unknown, msg) + ctx = callError(ctx, s.hooks, twerr) + } + callResponseSent(ctx, s.hooks) +} + +func (s *agentDispatchQueueServer) ServiceDescriptor() ([]byte, int) { + return twirpFileDescriptor11, 0 +} + +func (s *agentDispatchQueueServer) ProtocGenTwirpVersion() string { + return "v8.1.3" +} + +// PathPrefix returns the base service path, in the form: "//./" +// that is everything in a Twirp route except for the . This can be used for routing, +// for example to identify the requests that are targeted to this service in a mux. +func (s *agentDispatchQueueServer) PathPrefix() string { + return baseServicePath(s.pathPrefix, "livekit", "AgentDispatchQueue") +} + +var twirpFileDescriptor11 = []byte{ + // 1804 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x58, 0xcd, 0x72, 0x1b, 0xc7, + 0x11, 0xd6, 0x02, 0x04, 0x08, 0x34, 0x08, 0x10, 0x1c, 0x93, 0xd4, 0x6a, 0x65, 0xfe, 0x78, 0xe3, + 0xb2, 0x68, 0xba, 0x02, 0x39, 0x74, 0xec, 0x8a, 0x64, 0x3b, 0x16, 0xfe, 0x44, 0x42, 0xa6, 0x29, + 0x68, 0x40, 0x26, 0x8e, 0x2f, 0x5b, 0x0b, 0xec, 0x08, 0x5a, 0x09, 0xfb, 0xa3, 0xdd, 0x81, 0x42, + 0xba, 0xf2, 0x00, 0xca, 0x39, 0xe7, 0xbc, 0x40, 0xce, 0x39, 0xe9, 0x94, 0x27, 0x48, 0x8e, 0xa9, + 0xca, 0x3d, 0x97, 0x3c, 0x45, 0x6a, 0x7e, 0x76, 0xb1, 0x0b, 0x2c, 0x45, 0x33, 0xd1, 0x09, 0x3b, + 0xdd, 0xdf, 0x7c, 0x3d, 0xd3, 0xdd, 0xd3, 0xdd, 0x24, 0xe8, 0x13, 0xfb, 0x15, 0x79, 0x61, 0x53, + 0xc3, 0x1c, 0x13, 0x97, 0x1a, 0x96, 0x1d, 0xfa, 0x26, 0x1d, 0x3d, 0x33, 0x5e, 0x4e, 0xc9, 0x94, + 0x34, 0xfc, 0xc0, 0xa3, 0x1e, 0x5a, 0x96, 0x18, 0x6d, 0x67, 0xec, 0x79, 0xe3, 0x09, 0xb9, 0xcb, + 0xc5, 0xc3, 0xe9, 0xd3, 0xbb, 0xd4, 0x76, 0x48, 0x48, 0x4d, 0xc7, 0x17, 0x48, 0xed, 0xfd, 0x6c, + 0x36, 0xa9, 0x5d, 0x8f, 0xb4, 0x8e, 0x67, 0x91, 0x49, 0x18, 0x4b, 0xbd, 0xf1, 0x98, 0x04, 0x77, + 0x3d, 0x9f, 0xda, 0x9e, 0x2b, 0xa5, 0xfa, 0xbf, 0x96, 0xa0, 0xf6, 0x84, 0x9d, 0xc1, 0x7a, 0xe4, + 0x0d, 0x7b, 0xae, 0x3f, 0xa5, 0x68, 0x0b, 0x40, 0xd0, 0xba, 0xa6, 0x43, 0x54, 0x65, 0x57, 0xd9, + 0x2b, 0xe3, 0x32, 0x97, 0x9c, 0x98, 0x0e, 0x41, 0xb7, 0xa1, 0x1c, 0x78, 0x9e, 0x23, 0xb4, 0x39, + 0xae, 0x2d, 0x31, 0x01, 0x57, 0xde, 0x81, 0x55, 0xdb, 0x22, 0x8e, 0xef, 0x51, 0xe2, 0x8e, 0x2e, + 0x8c, 0x17, 0xe4, 0x42, 0xcd, 0x73, 0x48, 0x2d, 0x21, 0xfe, 0x96, 0x5c, 0xa0, 0x1d, 0x28, 0x39, + 0x84, 0x9a, 0x96, 0x49, 0x4d, 0x75, 0x89, 0x21, 0x5a, 0xf9, 0xbf, 0xf5, 0x15, 0x1c, 0x0b, 0xd1, + 0x31, 0x80, 0x49, 0x69, 0x60, 0x0f, 0xa7, 0x94, 0x84, 0x6a, 0x61, 0x37, 0xbf, 0x57, 0x39, 0xb8, + 0xd3, 0x90, 0x37, 0x6b, 0xa4, 0x8f, 0xdc, 0x68, 0xc6, 0xc8, 0xae, 0x4b, 0x83, 0x0b, 0xc1, 0x95, + 0xd8, 0x8f, 0xb6, 0x01, 0x2c, 0xe2, 0x4f, 0xbc, 0x0b, 0x87, 0xb8, 0x54, 0x2d, 0xf2, 0x23, 0x25, + 0x24, 0xe8, 0x01, 0xd4, 0x02, 0xe6, 0xe1, 0x80, 0x1a, 0xbe, 0x37, 0xb1, 0x47, 0x17, 0xea, 0xf2, + 0xae, 0xb2, 0x57, 0x3b, 0xb8, 0x15, 0x5b, 0x7c, 0xe4, 0x0d, 0xb1, 0x40, 0xf4, 0x39, 0x00, 0x57, + 0x83, 0xe4, 0x12, 0xfd, 0x1a, 0x80, 0x9c, 0xfb, 0x76, 0x40, 0x42, 0xc3, 0xa4, 0x6a, 0x69, 0x57, + 0xd9, 0xab, 0x1c, 0x68, 0x0d, 0x11, 0xc8, 0x46, 0x14, 0xc8, 0xc6, 0x69, 0x14, 0xc8, 0xa3, 0x1b, + 0xb8, 0x2c, 0xf1, 0x4d, 0xfa, 0x5a, 0x51, 0xd0, 0x01, 0x94, 0x7e, 0x4f, 0x86, 0xcf, 0x3c, 0xef, + 0x45, 0xa8, 0x96, 0xf9, 0x6d, 0x37, 0x63, 0xdb, 0xbf, 0x15, 0x8a, 0xb6, 0xe7, 0x3e, 0xb5, 0xc7, + 0x38, 0xc6, 0xa1, 0x07, 0x50, 0x11, 0x67, 0x36, 0x9f, 0x52, 0x12, 0xa8, 0x95, 0x2b, 0x8d, 0x2a, + 0x18, 0xf8, 0x86, 0x26, 0xc3, 0xbf, 0x56, 0x14, 0xed, 0x6b, 0x58, 0x9d, 0xf3, 0x1d, 0xaa, 0x43, + 0x9e, 0x85, 0x4d, 0xc4, 0x9d, 0x7d, 0xa2, 0x75, 0x28, 0xbc, 0x32, 0x27, 0xd3, 0x28, 0xda, 0x62, + 0x71, 0x3f, 0xf7, 0x2b, 0xa5, 0x55, 0x85, 0x8a, 0x31, 0xbb, 0x75, 0xab, 0x06, 0x2b, 0x46, 0xe2, + 0x40, 0xfa, 0x9f, 0x97, 0xa0, 0x1c, 0x47, 0x0a, 0xa9, 0x90, 0xb3, 0x2d, 0xc1, 0xdb, 0x2a, 0xbd, + 0xe9, 0x17, 0x9e, 0x7b, 0xc3, 0x5e, 0x07, 0xe7, 0x6c, 0x0b, 0xed, 0x43, 0x69, 0x1c, 0x78, 0x53, + 0xdf, 0xb0, 0x2d, 0x61, 0xa3, 0x05, 0x6f, 0xfa, 0xcb, 0x5c, 0xd4, 0xeb, 0x1c, 0xdd, 0xc0, 0xf2, + 0xd3, 0x62, 0x7e, 0xfa, 0x14, 0x8a, 0x21, 0x35, 0xe9, 0x34, 0xe4, 0x89, 0x55, 0x3b, 0x50, 0x17, + 0x73, 0x62, 0xc0, 0xf5, 0x58, 0xe2, 0xd0, 0xcf, 0xa1, 0x60, 0xb3, 0x2c, 0xe1, 0x79, 0x56, 0x39, + 0xb8, 0x79, 0x49, 0x12, 0x61, 0x81, 0x42, 0x0d, 0xa8, 0xc4, 0xaf, 0xd3, 0xb6, 0xd4, 0x02, 0x3f, + 0x4f, 0xf5, 0x4d, 0x1f, 0x22, 0x69, 0xaf, 0x83, 0x67, 0xdf, 0x16, 0xd2, 0x61, 0x99, 0xbf, 0x07, + 0xdb, 0x12, 0x79, 0xd5, 0x2a, 0xbf, 0xe9, 0x17, 0x99, 0xa4, 0xd7, 0xc1, 0xe2, 0xd7, 0x42, 0xb7, + 0xa1, 0x18, 0x90, 0x70, 0x3a, 0xa1, 0x3c, 0xad, 0x64, 0xae, 0x4b, 0x11, 0x73, 0x2f, 0x09, 0x02, + 0x2f, 0xe0, 0x49, 0x53, 0xc6, 0x62, 0x81, 0x34, 0x28, 0x99, 0x94, 0x12, 0xc7, 0xa7, 0x2c, 0x1f, + 0x94, 0xbd, 0x02, 0x8e, 0xd7, 0xe8, 0x1e, 0xc0, 0x28, 0x20, 0x26, 0x25, 0x16, 0xcb, 0x35, 0xb8, + 0x2a, 0xec, 0xb8, 0x2c, 0xd1, 0x4d, 0x8a, 0xbe, 0x81, 0x6a, 0x74, 0x76, 0xb1, 0xfb, 0xca, 0xa4, + 0xc1, 0x2b, 0xb3, 0x0d, 0x4d, 0x8a, 0xbe, 0x86, 0x95, 0x91, 0xe7, 0xf8, 0x13, 0x22, 0xad, 0xaf, + 0x5c, 0xb9, 0xbf, 0x12, 0xe3, 0x9b, 0xb4, 0x55, 0x81, 0xb2, 0x11, 0xc5, 0x5a, 0xff, 0x6b, 0x0e, + 0x4a, 0x8f, 0xbc, 0xe1, 0x21, 0x5b, 0x23, 0x2d, 0x91, 0x1e, 0x89, 0xf0, 0xf3, 0x04, 0xd9, 0x84, + 0xa2, 0x6f, 0x4e, 0x43, 0x22, 0xd2, 0xa3, 0x84, 0xe5, 0x6a, 0xce, 0x11, 0xf9, 0xeb, 0x38, 0xe2, + 0x73, 0x28, 0x8e, 0xbc, 0xa9, 0x4b, 0x43, 0x75, 0x89, 0xbf, 0xb6, 0xad, 0xe4, 0x4b, 0xe7, 0x27, + 0x6a, 0x88, 0x3c, 0x6a, 0x33, 0x14, 0x96, 0x60, 0xf4, 0x09, 0xac, 0x8d, 0x3c, 0x77, 0x34, 0x0d, + 0x02, 0x5e, 0xe0, 0x26, 0xb6, 0x63, 0x53, 0x9e, 0x23, 0x55, 0x5c, 0x4f, 0x28, 0x8e, 0x99, 0x5c, + 0x3b, 0x83, 0x4a, 0x82, 0x23, 0x91, 0xba, 0xca, 0x4f, 0x4c, 0xdd, 0x75, 0x28, 0x70, 0xbb, 0xfc, + 0xda, 0x55, 0x2c, 0x16, 0xfa, 0xbf, 0x15, 0xa8, 0x76, 0x64, 0x4c, 0xb8, 0x21, 0xf4, 0x0b, 0x28, + 0x84, 0x23, 0xcf, 0x27, 0x92, 0xf8, 0x76, 0x4c, 0x9c, 0x82, 0x0d, 0x18, 0x04, 0x0b, 0x64, 0xf4, + 0xcc, 0x73, 0xb3, 0x67, 0xbe, 0x0f, 0x35, 0xc7, 0x3c, 0x37, 0xe2, 0x5b, 0x88, 0x07, 0x53, 0x3d, + 0xba, 0x81, 0xab, 0x8e, 0x79, 0xde, 0x8e, 0xc5, 0xec, 0x15, 0x7e, 0x01, 0x1b, 0x0c, 0xcb, 0x1f, + 0x7b, 0x68, 0xf8, 0x24, 0x30, 0x1c, 0xdb, 0x9d, 0x52, 0x22, 0x5c, 0x71, 0xa4, 0x60, 0xe4, 0x98, + 0xe7, 0x03, 0xae, 0xed, 0x93, 0xe0, 0x3b, 0xae, 0x7b, 0xad, 0x28, 0xad, 0x35, 0x58, 0x35, 0xd2, + 0x46, 0x5a, 0x2a, 0x6c, 0x1a, 0x99, 0x5c, 0xfa, 0x4b, 0x78, 0x2f, 0x3a, 0x3f, 0x77, 0x90, 0xa8, + 0x7f, 0x68, 0x1f, 0xd6, 0x1c, 0xdb, 0x35, 0x9e, 0x06, 0x84, 0x18, 0x23, 0xd3, 0x37, 0x47, 0x36, + 0x15, 0xe5, 0xaa, 0x8a, 0x57, 0x1d, 0xdb, 0x7d, 0x18, 0x10, 0xd2, 0x96, 0x62, 0xd4, 0x80, 0x22, + 0x0f, 0x51, 0xa8, 0xe6, 0xe6, 0x6a, 0x6a, 0xca, 0x33, 0x58, 0xa2, 0xf4, 0x7f, 0x28, 0x50, 0x6b, + 0x5a, 0x2c, 0x12, 0x21, 0x26, 0x2f, 0xa7, 0x24, 0xa4, 0xe8, 0x13, 0x58, 0x7a, 0xee, 0x0d, 0x59, + 0xcc, 0xf2, 0x6f, 0xab, 0x1e, 0x1c, 0x74, 0xad, 0x4a, 0xf6, 0x25, 0xdc, 0x14, 0xd8, 0xc5, 0x84, + 0xca, 0x4b, 0x2f, 0x6e, 0x70, 0x40, 0x7b, 0x2e, 0xaf, 0x98, 0x23, 0x93, 0xef, 0xa8, 0xa5, 0x81, + 0x6a, 0x5c, 0x42, 0xa5, 0xdf, 0x83, 0xd5, 0xf8, 0x42, 0xa1, 0xef, 0xb9, 0x21, 0x41, 0x1f, 0xa5, + 0x6e, 0x84, 0x16, 0x6f, 0x24, 0x2e, 0xa3, 0x7f, 0x0a, 0xd5, 0x43, 0x42, 0x79, 0xe3, 0x13, 0xae, + 0xd8, 0x81, 0xe2, 0x73, 0x6f, 0x68, 0x64, 0x54, 0x71, 0xfe, 0x63, 0xe9, 0x5f, 0x40, 0x2d, 0xda, + 0x21, 0x6d, 0x7d, 0x08, 0xf9, 0xe7, 0xde, 0x90, 0xe3, 0xb3, 0x4d, 0x31, 0xb5, 0xfe, 0xc7, 0x1c, + 0xac, 0x1e, 0xdb, 0x21, 0x4d, 0xfa, 0x3d, 0xe9, 0x4a, 0xe5, 0x0a, 0x57, 0x7e, 0x1e, 0xbf, 0xac, + 0xdc, 0xdb, 0x5f, 0xd6, 0x91, 0x12, 0xbd, 0x2d, 0xb6, 0xed, 0x2b, 0x00, 0xdf, 0x1c, 0x13, 0x83, + 0x7a, 0x2f, 0x88, 0x2b, 0xcb, 0xc7, 0x6c, 0xeb, 0x29, 0x93, 0xf6, 0xcd, 0xb1, 0xed, 0x9a, 0x6c, + 0x62, 0x3a, 0xca, 0xe1, 0x32, 0x43, 0x73, 0x31, 0xdb, 0xbd, 0x0b, 0x7c, 0x6d, 0x84, 0xf6, 0x8f, + 0x84, 0x3f, 0x95, 0xc2, 0x51, 0x1e, 0x97, 0x98, 0x68, 0x60, 0xff, 0x48, 0x16, 0x82, 0x54, 0x86, + 0x65, 0x43, 0x98, 0xe6, 0x6d, 0x73, 0x66, 0xb8, 0xb5, 0x02, 0x60, 0xc4, 0x4c, 0xfa, 0x1f, 0xa0, + 0x3e, 0x73, 0xc5, 0xf5, 0x22, 0x86, 0x1e, 0xc0, 0xaa, 0x4b, 0xce, 0x69, 0x82, 0x9c, 0x3b, 0xe4, + 0x2d, 0xb7, 0xc2, 0x55, 0xb6, 0xa1, 0x1f, 0xdd, 0x4b, 0xff, 0x0c, 0xea, 0x98, 0x38, 0xde, 0x2b, + 0x72, 0x9d, 0xb0, 0xbf, 0x07, 0x6b, 0x89, 0x4d, 0xe2, 0xcc, 0xfa, 0x3f, 0x15, 0x46, 0x45, 0x83, + 0x8b, 0x64, 0x50, 0x75, 0x58, 0x16, 0x54, 0xe2, 0x2e, 0xa2, 0x59, 0x72, 0xae, 0x10, 0xf3, 0x5f, + 0x2b, 0x9c, 0x9b, 0xa4, 0x72, 0xd7, 0x9e, 0xa4, 0xe6, 0xa6, 0xa2, 0xfc, 0xb5, 0xa7, 0xa2, 0xab, + 0xc6, 0x9a, 0x2f, 0xd9, 0x75, 0xe3, 0x8b, 0x5d, 0xf3, 0x51, 0x6d, 0xc2, 0xba, 0x0c, 0x2f, 0x6f, + 0x32, 0x91, 0x67, 0xf4, 0x16, 0x6c, 0xcc, 0xc9, 0x25, 0xf1, 0xc7, 0x50, 0xe4, 0x39, 0x14, 0x51, + 0xaf, 0x2d, 0x34, 0x2a, 0x2c, 0x01, 0xfa, 0x63, 0x58, 0xef, 0xb3, 0xc6, 0x18, 0x2b, 0xae, 0xff, + 0x94, 0xd2, 0x0d, 0xfa, 0x26, 0x6c, 0xcc, 0x11, 0xca, 0xe0, 0xf6, 0x61, 0x03, 0x93, 0x70, 0xea, + 0xbc, 0x3b, 0x53, 0x2a, 0x6c, 0xce, 0x33, 0xce, 0x6c, 0xb5, 0x4d, 0x77, 0x44, 0x26, 0xef, 0xd2, + 0xd6, 0x3c, 0xe3, 0xcc, 0x56, 0x87, 0xb0, 0x59, 0xe5, 0x5d, 0xda, 0x9a, 0x67, 0x94, 0xb6, 0x76, + 0x60, 0xeb, 0x90, 0xd0, 0x8c, 0x0e, 0x17, 0xa5, 0xc4, 0x6f, 0x60, 0xfb, 0x32, 0x80, 0xcc, 0x8d, + 0x5f, 0xb2, 0x21, 0x86, 0x49, 0x64, 0x81, 0x7d, 0x7f, 0xa1, 0xbd, 0x25, 0x77, 0x49, 0xac, 0xfe, + 0x3d, 0xec, 0x9e, 0xf9, 0x96, 0x49, 0xc9, 0xe5, 0xb6, 0xff, 0x47, 0xe6, 0xdf, 0xc1, 0x07, 0x6f, + 0x61, 0xfe, 0x7f, 0x0e, 0xbd, 0xff, 0xa7, 0x1c, 0xac, 0xce, 0x15, 0x73, 0xf4, 0x01, 0x6c, 0x3d, + 0x39, 0xeb, 0x9e, 0x75, 0x3b, 0xc6, 0xa3, 0xc7, 0x2d, 0x63, 0x70, 0xda, 0x3c, 0x3d, 0x1b, 0x18, + 0x67, 0x27, 0x83, 0x7e, 0xb7, 0xdd, 0x7b, 0xd8, 0xeb, 0x76, 0xea, 0x37, 0xd0, 0xfb, 0xa0, 0x2e, + 0x42, 0x84, 0xa4, 0xae, 0x64, 0x13, 0x74, 0x7a, 0x83, 0x7e, 0xf3, 0xb4, 0x7d, 0xd4, 0x3b, 0x39, + 0xac, 0xe7, 0xd0, 0x16, 0xdc, 0x5a, 0x84, 0xe0, 0xb3, 0x93, 0x13, 0xa6, 0xce, 0xa3, 0x1d, 0xb8, + 0xbd, 0xa8, 0x1e, 0x9c, 0xb5, 0xdb, 0xdd, 0x6e, 0xa7, 0xdb, 0xa9, 0x2f, 0x65, 0x1f, 0xe0, 0x61, + 0xb3, 0x77, 0xdc, 0xed, 0xd4, 0x0b, 0xd9, 0xdb, 0xdb, 0xcd, 0x93, 0x76, 0xf7, 0x98, 0x01, 0x8a, + 0xd9, 0xe6, 0xbb, 0xdf, 0xf7, 0x7b, 0xb8, 0xdb, 0xa9, 0x2f, 0xef, 0xff, 0x00, 0x68, 0x71, 0xc4, + 0x43, 0x1f, 0xc2, 0x6e, 0x74, 0x09, 0xe3, 0xb8, 0xf7, 0x5d, 0xef, 0xd4, 0x18, 0xb4, 0x1f, 0xf7, + 0xbb, 0x73, 0xae, 0xd9, 0x06, 0x2d, 0x13, 0xd5, 0x3c, 0xec, 0x9e, 0x9c, 0xd6, 0x95, 0x83, 0xbf, + 0x2f, 0x03, 0x6a, 0xb2, 0x3f, 0xfb, 0x53, 0x61, 0x41, 0x5f, 0xc1, 0xb2, 0x1c, 0x28, 0xd0, 0x6c, + 0x18, 0x4a, 0xcf, 0x4c, 0x9a, 0xba, 0xa8, 0x90, 0xc1, 0xbf, 0x07, 0x45, 0x31, 0x21, 0xa0, 0xd9, + 0x28, 0x96, 0x1a, 0x32, 0xb4, 0x9b, 0x0b, 0x72, 0xb9, 0xf5, 0x1b, 0x28, 0x45, 0x8d, 0x11, 0xcd, + 0x0c, 0xcc, 0x8d, 0x0d, 0xda, 0xad, 0x0c, 0x8d, 0x24, 0x68, 0x41, 0x39, 0x6e, 0x53, 0x68, 0x86, + 0x9b, 0xef, 0x77, 0x9a, 0x96, 0xa5, 0x4a, 0x72, 0xc8, 0xda, 0x9f, 0xe2, 0x48, 0x37, 0xba, 0x14, + 0xc7, 0x7c, 0xab, 0x38, 0x81, 0x6a, 0xaa, 0xd4, 0xa3, 0xad, 0xf9, 0x33, 0xa7, 0x5a, 0x83, 0xb6, + 0x7d, 0x99, 0x7a, 0xc6, 0x97, 0xaa, 0xd2, 0x09, 0xbe, 0xac, 0x76, 0x90, 0xe0, 0xcb, 0x2c, 0xee, + 0xe8, 0x09, 0xd4, 0xd2, 0xa5, 0x18, 0x6d, 0x27, 0x6e, 0x93, 0x51, 0xf5, 0xb5, 0x9d, 0x4b, 0xf5, + 0x33, 0xca, 0x74, 0xc5, 0x4d, 0x50, 0x66, 0x16, 0xf7, 0x04, 0x65, 0x76, 0xa9, 0x66, 0x94, 0xe9, + 0xc2, 0x9a, 0xa0, 0xcc, 0xac, 0xe1, 0x09, 0xca, 0xec, 0x8a, 0x8c, 0x6c, 0xd8, 0xcc, 0x2e, 0xb8, + 0xe8, 0xa3, 0x64, 0x52, 0x5e, 0x5e, 0x36, 0xb5, 0x3b, 0x57, 0xe2, 0xa4, 0xa9, 0x00, 0x6e, 0x5d, + 0x5a, 0x29, 0xd1, 0xc7, 0x31, 0xcb, 0x55, 0x75, 0x5a, 0xdb, 0xff, 0x29, 0x50, 0x61, 0xb3, 0xf5, + 0xf0, 0x87, 0x9f, 0x8d, 0x6d, 0xfa, 0x6c, 0x3a, 0x6c, 0x8c, 0x3c, 0xe7, 0xae, 0xdc, 0x27, 0xfe, + 0xc9, 0x38, 0xf2, 0x26, 0x91, 0xe0, 0x2f, 0xb9, 0xea, 0xb1, 0xfd, 0x8a, 0x7c, 0xcb, 0xd2, 0x83, + 0xa9, 0xfe, 0x93, 0xab, 0xc9, 0xf5, 0xfd, 0xfb, 0x5c, 0x30, 0x2c, 0xf2, 0x2d, 0x9f, 0xfd, 0x37, + 0x00, 0x00, 0xff, 0xff, 0xac, 0x48, 0x04, 0x62, 0xd4, 0x14, 0x00, 0x00, +} diff --git a/magefile.go b/magefile.go index 5b42cfd6d..057caf6f0 100644 --- a/magefile.go +++ b/magefile.go @@ -72,6 +72,7 @@ func Proto() error { "livekit_connector_twilio.proto", "livekit_agent_simulation.proto", "livekit_agent_worker.proto", + "livekit_agent_dispatch_queue.proto", } agentProtoFiles := []string{ diff --git a/protobufs/livekit_agent_dispatch_queue.proto b/protobufs/livekit_agent_dispatch_queue.proto new file mode 100644 index 000000000..a1726b860 --- /dev/null +++ b/protobufs/livekit_agent_dispatch_queue.proto @@ -0,0 +1,316 @@ +// Copyright 2026 LiveKit, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package livekit; +option go_package = "github.com/livekit/protocol/livekit"; +option csharp_namespace = "LiveKit.Proto"; +option ruby_package = "LiveKit::Proto"; + +import "google/protobuf/timestamp.proto"; +import "livekit_agent_dispatch.proto"; +import "livekit_models.proto"; +import "logger/options.proto"; + +// AgentDispatchQueue accepts dispatches to run later, as project capacity +// allows, instead of failing at the concurrency cap the way +// AgentDispatchService.CreateDispatch does. A queued job becomes a real +// AgentDispatch only once the queue admits it. +// +// Enqueue is a batch because the queue exists to take thousands of dispatches +// in one request and let admission control pace them against the project's +// remaining capacity. +// +// Implemented in cloud only; OSS livekit-server does not serve this service. +// The project is taken from the caller's credentials, never from the request. +service AgentDispatchQueue { + rpc AddJobs(AddJobsRequest) returns (AddJobsResponse); + rpc GetJob(GetJobRequest) returns (GetJobResponse); + rpc ListJobs(ListJobsRequest) returns (ListJobsResponse); + rpc RemoveJob(RemoveJobRequest) returns (RemoveJobResponse); + rpc RetryJobs(RetryJobsRequest) returns (RetryJobsResponse); + + // Group operations. The server returns Unimplemented for all five until the + // group model lands (AP-976). + rpc ListJobGroups(ListJobGroupsRequest) returns (ListJobGroupsResponse); + rpc PauseJobGroup(PauseJobGroupRequest) returns (PauseJobGroupResponse); + rpc ResumeJobGroup(ResumeJobGroupRequest) returns (ResumeJobGroupResponse); + rpc CancelJobGroup(CancelJobGroupRequest) returns (CancelJobGroupResponse); + rpc DeleteJobGroup(DeleteJobGroupRequest) returns (DeleteJobGroupResponse); + + rpc GetDispatchQueueConfig(GetDispatchQueueConfigRequest) returns (GetDispatchQueueConfigResponse); + rpc UpdateDispatchQueueConfig(UpdateDispatchQueueConfigRequest) returns (UpdateDispatchQueueConfigResponse); +} + +enum QueuedJobStatus { + QUEUED_JOB_STATUS_UNSPECIFIED = 0; + // Awaiting capacity, or waiting on start_after. + QUEUED_JOB_STATUS_QUEUED = 1; + // Admitted; CreateDispatch in flight. + QUEUED_JOB_STATUS_DISPATCHING = 2; + // Dispatch created, agent job live. + QUEUED_JOB_STATUS_RUNNING = 3; + QUEUED_JOB_STATUS_SUCCEEDED = 4; + QUEUED_JOB_STATUS_FAILED = 5; + // Removed, or cancelled with its group, before it was admitted. + QUEUED_JOB_STATUS_CANCELLED = 6; + // Still queued at expires_at; never dispatched. Includes a job whose + // start_after never arrived before it expired. + QUEUED_JOB_STATUS_EXPIRED = 7; +} + +// What to dispatch. Mirrors CreateAgentDispatchRequest so that a queued job and +// an immediate dispatch describe the same work. +message QueuedJobInput { + // Must match the agent_name registered by the agent server. + string agent_name = 1; + // Required. The queue does not invent room names; a caller wanting one room + // per job supplies its own unique name. + string room_name = 2; + // Required, unique per project. Re-adding with the same key returns the + // existing job rather than dispatching twice. + string idempotency_key = 3; + + string metadata = 4 [(logger.sensitivity) = SENSITIVITY_PII]; + map attributes = 5 [(logger.sensitivity) = SENSITIVITY_PII]; + string deployment = 6; + JobRestartPolicy restart_policy = 7; + + // Never dispatch after this time; the job goes to EXPIRED instead. Capped at + // 8 days out to stay inside the row retention window, which also bounds + // start_after. + optional google.protobuf.Timestamp expires_at = 8; + // Per-job callbacks, signed with the project key, as with Egress per-request + // webhooks. Project-level webhooks fire regardless. + repeated WebhookConfig webhooks = 9; + + // Hold the job until this time. A floor, not an appointment: the job still + // waits on capacity once eligible, and eligibility only filters the FIFO + // scan - order stays created_at, so a held job keeps its original place in + // line. Must be before expires_at. + optional google.protobuf.Timestamp start_after = 11; +} + +message QueuedJob { + string id = 1 [(logger.name) = "jobID"]; + optional string group_id = 2 [(logger.name) = "groupID"]; + QueuedJobStatus status = 3; + QueuedJobInput input = 4; + + // Set once dispatch is invoked; the join point into the dispatch APIs. + string dispatch_id = 5 [(logger.name) = "dispatchID"]; + // Set once the room is created. + string room_id = 6 [(logger.name) = "roomID"]; + + // JSON the agent writes back before exiting; opaque to the queue and carried + // on the terminal webhook. + string result = 7 [(logger.sensitivity) = SENSITIVITY_PII]; + // Set on FAILED, including exhaustion of infra retries. + string error = 8; + // Dispatch attempts made by the queue. Counts infra-level retries before a + // dispatch succeeds, not agent-side failures. + int32 attempts = 9; + + google.protobuf.Timestamp created_at = 10; + google.protobuf.Timestamp dispatched_at = 11; + google.protobuf.Timestamp completed_at = 12; +} + +message JobGroup { + string id = 1 [(logger.name) = "groupID"]; + // A paused group admits nothing; jobs already in flight run to completion. + bool paused = 2; + google.protobuf.Timestamp created_at = 3; + repeated StatusCount counts = 4; + // Jobs from this group running at once, as set when the group was created. + // Zero means the dispatcher default applies. + uint32 concurrency_limit = 5; + + // Proto3 forbids enum map keys, so counts by status are a repeated pair. + message StatusCount { + QueuedJobStatus status = 1; + uint32 count = 2; + } +} + +// Which slice of the project's queued traffic a DispatchLimit applies to. +enum DispatchLimitScope { + // The project's whole queue. + DISPATCH_LIMIT_SCOPE_UNSPECIFIED = 0; + // QueuedJobInput.agent_name. + DISPATCH_LIMIT_SCOPE_AGENT = 1; +} + +// One limit over a slice of the project's queued traffic. A job is evaluated +// against every limit it matches and the smallest remaining budget wins. +// Per-group limits are set on the group instead, at AddJobsRequest. +// +// These bound what this queue admits. They do not bound sessions started +// outside it, including direct AgentDispatchService.CreateDispatch calls, so +// they are not a cap on an agent's total concurrency. +message DispatchLimit { + DispatchLimitScope scope = 1; + // Which value of the scoped attribute this limit covers. Empty with a scope + // set means every distinct value gets its own budget of this size, so one + // rule can cover all agents without enumerating them. + string key = 2; + + // Jobs from this scope running at once. Unset is unlimited; 0 blocks the + // scope without touching its jobs. + optional uint32 max_concurrent = 4; + // Dispatch starts allowed in any rolling 60 seconds - not calendar minutes. + // The scheduler releases this budget in slices across admission rounds, so a + // minute's worth never lands at once. Unset is unrated. + optional uint32 max_starts_per_minute = 5; +} + +message DispatchQueueConfig { + // The queue stops admitting while free project capacity would fall below + // this. Everything else the project runs - sessions a user started, direct + // AgentDispatchService.CreateDispatch calls, anything not from this queue - + // draws on the same capacity, and this is what the queue leaves for it. + // + // The asymmetry is the point: a queued job that cannot get capacity waits, + // which is what the queue is for. A request from anywhere else has nowhere + // to wait - it fails with quota exceeded. So the queue must never take the + // project's last capacity, however much it still has to drain. + // + // Size it to the demand you cannot afford to reject, NOT to the peak + // concurrency of that other work - admission already reads capacity + // REMAINING, so steady-state load lowers what the queue may take on its + // own. A project starting 5 sessions/sec wants roughly 10-20 here even if + // it runs 500 at once. + uint32 min_free_capacity = 1; + + repeated DispatchLimit limits = 2; +} + +message AddJobsRequest { + // Up to 1,000 per request; clients loop to add more. + repeated QueuedJobInput jobs = 1; + // Attach every job in this request to a group, created on first use. + optional string group_id = 2 [(logger.name) = "groupID"]; + // Jobs from this group to run at once. Applied when the group is created and + // ignored on later adds to the same group. Unset uses the dispatcher + // default. Group limits live here rather than in DispatchQueueConfig because + // groups are short-lived and would otherwise churn the project config. + optional uint32 group_concurrency_limit = 3; +} + +message AddJobsResponse { + // Same order and length as the request. Validation is atomic: if any input + // is invalid nothing is enqueued and the error enumerates every bad entry, + // so a rejected batch is safe to fix and resend in one pass. An input whose + // idempotency_key already existed yields the pre-existing job unchanged. + repeated QueuedJob jobs = 1; +} + +message GetJobRequest { + string job_id = 1 [(logger.name) = "jobID"]; +} + +message GetJobResponse { + QueuedJob job = 1; +} + +message ListJobsRequest { + optional string group_id = 1 [(logger.name) = "groupID"]; + optional QueuedJobStatus status = 2; + optional TokenPagination page_token = 3; + optional int32 page_size = 4; +} + +message ListJobsResponse { + repeated QueuedJob jobs = 1; + TokenPagination next_page_token = 2; +} + +// Cancels a job that has not been admitted yet (QUEUED -> CANCELLED). A job +// already DISPATCHING or RUNNING is left alone; tear down the live session +// through DeleteDispatch or the room APIs instead. +message RemoveJobRequest { + string job_id = 1 [(logger.name) = "jobID"]; +} + +message RemoveJobResponse {} + +// Re-queues jobs in a FAILED or EXPIRED state, reusing their rows and +// idempotency keys instead of minting new jobs. Jobs in any other state are +// returned untouched. +message RetryJobsRequest { + repeated string job_ids = 1 [(logger.name) = "jobIDs"]; + // Replaces expires_at on the retried jobs. + optional google.protobuf.Timestamp expires_at = 2; + // Replaces start_after on the retried jobs, to hold a retry back rather than + // re-queueing it immediately. Unset clears any start_after the job carried, + // since the original hold has already elapsed. + optional google.protobuf.Timestamp start_after = 3; +} + +message RetryJobsResponse { + repeated QueuedJob jobs = 1; +} + +message ListJobGroupsRequest {} + +message ListJobGroupsResponse { + repeated JobGroup groups = 1; +} + +// On every group operation below, an unset group_id applies the operation at +// project scope, across grouped and ungrouped jobs alike. +message PauseJobGroupRequest { + optional string group_id = 1 [(logger.name) = "groupID"]; +} + +message PauseJobGroupResponse {} + +message ResumeJobGroupRequest { + optional string group_id = 1 [(logger.name) = "groupID"]; +} + +message ResumeJobGroupResponse {} + +// Cancels the queued jobs in the group; jobs already in flight run to +// completion. +message CancelJobGroupRequest { + optional string group_id = 1 [(logger.name) = "groupID"]; +} + +message CancelJobGroupResponse {} + +// Cancels the remaining queued jobs and hides the group and its terminal jobs +// from listings. Rows are kept for the retention window. +message DeleteJobGroupRequest { + optional string group_id = 1 [(logger.name) = "groupID"]; +} + +message DeleteJobGroupResponse {} + +message GetDispatchQueueConfigRequest {} + +message GetDispatchQueueConfigResponse { + DispatchQueueConfig config = 1; +} + +// Replaces the stored config wholesale, so an omitted limit is a removed +// limit. Read-modify-write to change one field. +message UpdateDispatchQueueConfigRequest { + DispatchQueueConfig config = 1; +} + +message UpdateDispatchQueueConfigResponse { + DispatchQueueConfig config = 1; +}