Skip to main content
Glama
firebase
by firebase
background_action.go6.88 kB
// Copyright 2025 Google LLC // // 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. // // SPDX-License-Identifier: Apache-2.0 package core import ( "context" "github.com/firebase/genkit/go/core/api" ) // StartOpFunc starts a background operation. type StartOpFunc[In, Out any] = func(ctx context.Context, input In) (*Operation[Out], error) // CheckOpFunc checks the status of a background operation. type CheckOpFunc[Out any] = func(ctx context.Context, op *Operation[Out]) (*Operation[Out], error) // CancelOpFunc cancels a background operation. type CancelOpFunc[Out any] = func(ctx context.Context, op *Operation[Out]) (*Operation[Out], error) // Operation represents a long-running operation started by a background action. type Operation[Out any] struct { Action string // Key of the action that created this operation. ID string // ID of the operation. Done bool // Whether the operation is complete. Output Out // Result when done. Error error // Error if the operation failed. Metadata map[string]any // Additional metadata. } // BackgroundActionDef is a background action that can be used to start, check, and cancel background operations. // // For internal use only. type BackgroundActionDef[In, Out any] struct { *ActionDef[In, *Operation[Out], struct{}] check *ActionDef[*Operation[Out], *Operation[Out], struct{}] // Sub-action that checks the status of a background operation. cancel *ActionDef[*Operation[Out], *Operation[Out], struct{}] // Sub-action that cancels a background operation. } // Start starts a background operation. func (b *BackgroundActionDef[In, Out]) Start(ctx context.Context, input In) (*Operation[Out], error) { return b.Run(ctx, input, nil) } // Check checks the status of a background operation. func (b *BackgroundActionDef[In, Out]) Check(ctx context.Context, op *Operation[Out]) (*Operation[Out], error) { return b.check.Run(ctx, op, nil) } // Cancel attempts to cancel a background operation. It returns an error if the background action does not support cancellation. func (b *BackgroundActionDef[In, Out]) Cancel(ctx context.Context, op *Operation[Out]) (*Operation[Out], error) { if !b.SupportsCancel() { return nil, NewError(UNAVAILABLE, "model %q does not support canceling operations", b.Name()) } return b.cancel.Run(ctx, op, nil) } // SupportsCancel returns whether the background action supports cancellation. func (b *BackgroundActionDef[In, Out]) SupportsCancel() bool { return b.cancel != nil } // Register registers the model with the given registry. func (b *BackgroundActionDef[In, Out]) Register(r api.Registry) { b.ActionDef.Register(r) b.check.Register(r) if b.cancel != nil { b.cancel.Register(r) } } // DefineBackgroundAction creates and registers a background action with three component actions func DefineBackgroundAction[In, Out any]( r api.Registry, name string, atype api.ActionType, metadata map[string]any, startFn StartOpFunc[In, Out], checkFn CheckOpFunc[Out], cancelFn CancelOpFunc[Out], ) *BackgroundActionDef[In, Out] { a := NewBackgroundAction(name, atype, metadata, startFn, checkFn, cancelFn) a.Register(r) return a } // NewBackgroundAction creates a new background action without registering it. func NewBackgroundAction[In, Out any]( name string, atype api.ActionType, metadata map[string]any, startFn StartOpFunc[In, Out], checkFn CheckOpFunc[Out], cancelFn CancelOpFunc[Out], ) *BackgroundActionDef[In, Out] { if name == "" { panic("core.NewBackgroundAction: name is required") } if startFn == nil { panic("core.NewBackgroundAction: startFn is required") } if checkFn == nil { panic("core.NewBackgroundAction: checkFn is required") } key := api.KeyFromName(atype, name) startAction := NewAction(name, atype, metadata, nil, func(ctx context.Context, input In) (*Operation[Out], error) { op, err := startFn(ctx, input) if err != nil { return nil, err } op.Action = key return op, nil }) checkAction := NewAction(name, api.ActionTypeCheckOperation, metadata, nil, func(ctx context.Context, op *Operation[Out]) (*Operation[Out], error) { updatedOp, err := checkFn(ctx, op) if err != nil { return nil, err } updatedOp.Action = key return updatedOp, nil }) var cancelAction *ActionDef[*Operation[Out], *Operation[Out], struct{}] if cancelFn != nil { cancelAction = NewAction(name, api.ActionTypeCancelOperation, metadata, nil, func(ctx context.Context, op *Operation[Out]) (*Operation[Out], error) { cancelledOp, err := cancelFn(ctx, op) if err != nil { return nil, err } cancelledOp.Action = key return cancelledOp, nil }) } return &BackgroundActionDef[In, Out]{ ActionDef: startAction, check: checkAction, cancel: cancelAction, } } // LookupBackgroundAction looks up a background action by key (which includes the action type, provider, and name). func LookupBackgroundAction[In, Out any](r api.Registry, key string) *BackgroundActionDef[In, Out] { atype, provider, id := api.ParseKey(key) name := api.NewName(provider, id) startAction := ResolveActionFor[In, *Operation[Out], struct{}](r, atype, name) if startAction == nil { return nil } checkAction := ResolveActionFor[*Operation[Out], *Operation[Out], struct{}](r, api.ActionTypeCheckOperation, name) if checkAction == nil { return nil } cancelAction := ResolveActionFor[*Operation[Out], *Operation[Out], struct{}](r, api.ActionTypeCancelOperation, name) return &BackgroundActionDef[In, Out]{ ActionDef: startAction, check: checkAction, cancel: cancelAction, } } // CheckOperation checks the status of a background operation by looking up the action and calling its Check method. func CheckOperation[In, Out any](ctx context.Context, r api.Registry, op *Operation[Out]) (*Operation[Out], error) { if op == nil { return nil, NewError(INVALID_ARGUMENT, "core.CheckOperation: operation is nil") } if op.Action == "" { return nil, NewError(INVALID_ARGUMENT, "core.CheckOperation: operation is missing original request information") } m := LookupBackgroundAction[In, Out](r, op.Action) if m == nil { return nil, NewError(INVALID_ARGUMENT, "core.CheckOperation: failed to resolve background model %q from original request", op.Action) } return m.Check(ctx, op) }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/firebase/genkit'

If you have feedback or need assistance with the MCP directory API, please join our Discord server