把函数打包进 Marketplace
用 Foundry DevOps 可以把函数打进 Marketplace 产品,让别人安装复用。这一篇讲打包方式、版本与 API 名解析、部署函数的特殊限制。
https://www.palantir.com/docs/foundry/functions/marketplace-functions/
原始标题:Function management > Functions in Marketplace
先记住这几条
写在前面
你可以使用 Foundry DevOps 将你的函数包含进 Marketplace 产品 中,供其他用户安装与复用。
把函数加入产品
把函数加入产品
要将一个函数加入产品,请创建一个产品。然后,如下面所示添加一个函数输出。

系统会提示你选择一个函数及其版本。

Including source code for code repositories
打包一个在代码仓库中创作的函数时,其底层仓库会自动作为产品中的一个附加输出被包含进来。虽然你可以选择将代码仓库与其源代码一起打包,但我们通常不鼓励为不打算以引导模式(bootstrap mode)安装的产品包含源代码。这是因为一个通过 Marketplace 安装的函数,并不需要其底层源代码就能成功执行。此外,代码仓库并不能保证开箱即可编译或构建。
如果你希望在安装后修改一个函数(例如修复 bug 或增强功能),我们建议直接修改原始函数、发布一个新版本的 Marketplace 产品,然后升级该安装。如果你不拥有所安装的产品,应向其维护者提交 bug 报告或功能请求。
Extended function execution requirements
使用扩展执行能力的函数有额外的 Marketplace 安装要求。这些能力包括从函数内部调用动作,以及获取存活时间(TTL)更长的认证令牌。在安装之前,管理员必须将目标项目添加到 Control Panel 中 Functions settings(函数设置) 下的 Extended function execution(扩展函数执行) 允许列表中。
关于允许列表的配置说明,请参阅 Functions settings。
版本与 API 名解析
版本与 API 名解析
当一个函数通过 Marketplace 安装时,其版本与 API 名称有两种解析方式:去重模式(deduplication mode)与稳定模式(stable mode)。
Deduplication mode
这是通过 Marketplace 安装时解析函数版本与 API 名称的历史默认行为。
在去重模式下,函数的版本解析如下:
- 当函数最初由一次安装创建时,其第一个版本发布在
0.1.0。 - 在后续安装(如升级)时,函数以其最新版本递增一个次版本号发布。例如,如果已安装函数的最新版本是
1.1.0,下一次安装将发布在1.2.0。
函数版本是不可变的。换句话说,一旦某个函数版本被发布,它就不能被修改或覆盖。
函数的 API 名称解析方式如下:
- 如果 API 名称已经被安装所用 Ontology 中的另一个函数占用,将通过追加递增的整数后缀来去重。例如,如果 API 名称
myFunction已被占用,该函数将以 API 名称myFunction1安装。如果该名称也被占用,它将以myFunction2安装,依此类推。 - 一旦已安装函数上存在某个 API 名称,该函数在后续安装(如升级)中保持该 API 名称。
函数 API 名称 在每个 Ontology 内是唯一的。准确地说,如果一个 Ontology 中已存在 API 名称为 myFunction 的函数,则同一 Ontology 中不能存在另一个具有相同 API 名称的函数。
Stable mode
:::callout{theme="neutral" title="Beta"}
稳定模式处于测试(beta)开发阶段,在你的租户中可能不可用。功能在积极开发期间可能发生变化。请联系 Palantir 支持在你的租户上启用此功能。
版本与 API 名称是你函数 API 的组成部分。因此在许多情况下,通过 Marketplace 打包与安装时保留它们是可取的。当与静态引用函数依赖的上游应用一起安装函数时,这一点尤其重要,例如 Developer Console 应用。
稳定模式不支持计算模块函数,因为这些函数在 Foundry 中有自己的版本管理行为。
在稳定模式下,函数的版本解析如下:
- 已安装的函数总是以其打包时的版本发布。
- 如果该版本对已安装函数已存在,将创建一个全新的函数;旧函数会被隐藏,其 API 名称会被移除。
创建新函数来解决版本冲突会影响上游应用。如果上游应用是同一安装的一部分,它会自动更新以引用新函数。否则,你需要手动更新它。
函数的 API 名称解析如下:
- 已安装的函数总是以它打包时所用的 API 名称发布。
- 如果该 API 名称已被另一个函数占用,将发生安装错误。要解决此冲突,你必须删除现有函数或更改其 API 名称。
部署型函数的处理
部署型函数的处理
函数要么运行在 serverless 执行模式,要么被部署到一个长期运行的容器中。Marketplace 将函数仓库的执行模式与函数本身一起打包,因此已安装的函数会以它在被打包环境中相同的方式运行。
How Marketplace packages function execution mode
函数执行模式是按仓库配置的,Marketplace 为同一部署支撑的所有函数打包一次。
对于处于部署模式的仓库,Marketplace 会捕获环境变量、资源请求与限制、扩缩容限制,以及其他关键部署配置细节。
Marketplace 不会将容器镜像作为固定值打包。相反,容器镜像在安装时根据被安装函数的版本解析,因此已安装的部署总是运行被安装函数的镜像。
要打包一个仓库处于部署模式的函数,该仓库必须存在一个部署,且它必须运行着你正在打包的函数版本。否则,打包会失败。要解决此问题,请启动或更新该部署,使其运行你想要打包的版本,或将仓库切换到 serverless 执行。
How Marketplace applies configuration during installation
当你安装或升级一个产品时,Marketplace 将打包好的执行模式与部署配置应用到目标环境。这等同于解锁安装,并手动配置执行以匹配产品被打包的环境。
如果打包的模式是部署式,Marketplace 会为已安装的仓库创建一个部署(如果尚不存在),将打包的部署配置应用到它,并启动该部署。
如果打包的模式是serverless,Marketplace 将已安装仓库设置为 serverless 执行。如果为该仓库已存在部署,Marketplace 会停止该安装。
Serverless 函数并非在每个租户上都可用。如果一个产品将某个函数以 serverless 模式打包,但目标环境不支持 serverless 执行,该函数会改为以部署模式安装。发生这种情况时,Marketplace 会以默认配置创建并启动一个部署。这保证了已安装函数可作为部署式函数运行。
:::callout{theme="warning" title="计算成本"}
部署式函数在其部署运行期间会产生计算成本,而 serverless 函数仅在执行时产生成本。因此,一个因目标环境不支持 serverless 执行而以部署模式安装的 serverless 函数,会产生长期运行部署的计算成本。
Limitations of deployed functions in Marketplace
Marketplace 中的部署式函数有以下限制。
Only one version of a function can be deployed at a time
一个部署运行函数的单一版本。当你升级一个包含部署式函数的 Marketplace 产品时,该函数以新版本重新发布,且该新版本会自动部署以取代之前部署的版本。
正在升级的安装之外的产品不会因该升级而更新。如果某个外部产品,或既不包含在 Marketplace 产品中也不属于关联产品(linked product)的产品,引用了部署式函数的某个特定版本,它的引用会继续指向旧版本。由于同一时刻只能部署一个函数版本,任何指向该函数旧版本的引用都会返回错误。
为避免此问题,你必须:
- 将部署式函数的消费者打包在同一个产品或关联产品中,使它们与函数一起升级。
- 尽可能使用 serverless 执行。Serverless 函数可以按需执行函数的不同版本,因此升级不会使对早期版本的引用失效。
Deployments restart during upgrades
对支撑部署式函数的长期运行容器的一些更改(例如更新它所配置的源),无法在该容器运行时应用。因此,作为 Marketplace 产品升级的一部分,每次升级时该部署可能被停止并重新启动,意味着函数可能经历停机。
静态函数输入
静态函数输入
此特性仅支持 TypeScript v1。
通过在安装时提供一个本地定义的函数,覆写随 Marketplace 产品附带的「静态」函数输入,可以修改函数行为的一部分。为此,你可以使用 @Static 装饰器指定某个函数可被覆写。
import { Function, Static, Double } from "@foundry/functions-api";
export class MyFunctions {
@Function()
public async modifyNumberByStaticFoo(
n: Double,
@Static() staticFunctionInput: (num: Double) => Promise<Double> = this.defaultFoo
): Promise<Double> {
return await staticFunctionInput(n);
}
private async defaultFoo(n: number) {
return -n;
}
}打包函数时,任何静态输入都会作为函数输入出现在安装过程中。安装者随后可以提供他们自己的函数逻辑,覆写默认行为。
自定义别名
自定义别名
自定义别名(custom aliases) 存储字符串值,例如配置参数、特性开关或环境特定设置。当你向 Marketplace 产品添加一个带自定义别名函数时,这些别名会自动作为 Inputs(输入) 下的可配置参数出现。安装者可以在不修改函数源代码的情况下,设置环境特定的值。
自定义别名在 TypeScript v2 与 Python 函数中受支持。与静态函数输入不同,自定义别名:
- 同时适用于 TypeScript v2 与 Python
- 允许安装者配置字符串值,而非函数逻辑
- 在 Marketplace 安装体验中支持描述与预设值
关于在函数中定义与使用自定义别名的细节,请参阅 Custom aliases。
模型别名
模型别名
你可以将那些通过模型别名(model aliases)引用语言模型的函数添加到 Marketplace 产品中。Marketplace 对这些别名施加了特定限制。
模型别名不能在安装期间重新映射。如果别名所引用的模型在目标环境中不可用,函数会在运行时无法解析该别名。
与自定义别名(在安装过程中作为可配置参数出现)不同,Marketplace 在运行时使用源仓库中配置的确切模型 RID 来解析模型别名。请确保别名所引用的模型,在将安装该产品的每个目标环境中都可用。
已知问题
已知问题
Interface inputs in Marketplace functions
接受接口作为输入参数的函数,可能在目标环境中抛出 MarketplaceSdkObjectMappingNotFound 错误。Marketplace 要求 SDK 绑定包含具体的对象类型,而不仅仅是接口。
如果函数声明了一个接口输入,而目标环境包含实现该接口的具体类型的对象,SDK 无法找到具体类型的映射。函数随后在运行时失败。
规避方法: 确保目标环境中使用的具体对象类型也存在于源环境中,然后将其显式包含在 Marketplace 打包的 SDK 中。这会生成所需的映射,使函数能够解析并使用该对象类型。
延伸阅读 · 相关页面
按主题横向跳转,不必顺着目录一篇篇读。
常见问题速答 · FAQ
关于「把函数打包进 Marketplace」,读者最常问的几个问题。