V2.0更新说明

引言

Fireboom2.0是一个值得骄傲的作品!其中最亮眼的特性是:多人协作支持极致性能提升

有内测用户讲,2.0升级后好像没啥变化,我打趣道:2.0样子没变,心变了

存储重构,支持协作

1.0版本存储层数据结构不合理,无法用github合并,只适用于单人开发,无法多人协作。而对团队而言,多人协作是不可或缺的功能。

在2.0版本中,我们对存储层数据结构进行了全面的重新设计和优化,不仅支持基于GitHub的离线协作,而且在架构上支持实时协作。

引擎重构,性能提升:

1.0版本存在性能问题,在表数量接近300时,常常内省失败,且构建的“超图”冗余过多,导致fireboom.config.json动辄十几个G,不仅编译较慢,而且运行时很消耗内存。

重构引擎,2.0的生成文件缩小 10 倍 ,运行内存缩小 10 倍,静态编译速度提升 5 倍

这还不够,进一步支持了OPERATION增量编译,实现了无感编译!

体验优化,流畅开发:

1.0版本也存在一些开发体验问题,其中最影响体验的是钩子服务与Fireboom服务的循环依赖。

2.0版本重构了钩子SDK,采用心跳上报的方式完美解决了该问题,钩子开发前所未有的流畅。

新功能和改进

接下来,我们详细介绍全部更新。

存储结构变更

旧版store 目录

store
├── hooks
│   ├── auth
│   ├── customize
│   ├── global
│   ├── hooks
│   └── uploads
├── list
│   ├── FbAuthentication
│   ├── FbDataSource
│   ├── FbOperation
│   ├── FbRole
│   ├── FbSDK
│   └── FbStorageBucket
└── object
    ├── global_config.json
    ├── global_operation_config.json
    ├── global_system_config.json
    └── operations

旧版存储有两类问题:

1,list目录中以json数组的方式存储所有数据源、OPERATION,任意API的变更,都会影响整体文件,导致多人协作时,经常冲突

2,相同业务存储过于分散,操作一个对象,要同时操作N个文件

新版store目录

store
├── authentication # 对应list/FbAuthentication
│   ├── auth0.json
├── config
│   ├── global.operation.json
│   └── global.setting.json
├── datasource # 对应list/FbDataSource
│   ├── main.json
│   ├── system.json
├── operation # 对应list/FbOperation
│   ├── xxx.graphql  # 对应exported/operations下的xxx.graphql
│   ├── xxx.json # 将hooks/hooks和list/FbOperation的文件合在一起
├── role # 对应list/FbRole
│   ├── admin.json
│   └── user.json
├── sdk
│   └── golang-server.json
└── storage # 对应list/FbStorageBucket
    └── aliyun.json

新版存储,重新设计了存储结构,完全解决了旧版的两大问题,且具备如下优势:

  • 方便合并:每个文件代表一个对象,例如OPERATION operation

  • 统一读取:OPERATION相关的业务都存储在了同一个json中

  • 方便管理:将exported/operations目录下.graphql文件移到了operation目录,和.json同名

构建物优化

构建物位于exported/generated目录,v1.0版本中fireboom.config.json文件中有很多冗余,动辄十几个G。

新版本将其拆分为了2个文件:fireboom.config.jsonfireboom.operations.json,且将冗余存储改为了引用存储,数十倍的减少了文件大小。小的构建物,成倍缩小了运行内存。

此外,文件的拆分也减少了GraphQL对象的转换次数,成倍提升了合成超图的速度。

增量编译

1.0版本任意一次OPERATION的编辑都会触发全量的OPERATION编译,造成巨大的性能浪费。新版本将全量编译改为了增量编译,极大提升了OPERATION的编译速度!

这取决于项目OPERATION的数量,OPEARTION越多,提升效果越显著!

Prisma数据源

2.0版本增加了一种特殊数据源:Prisma数据源,适用于数据库表数量较多的场景。

其主要用途如下:

  • 虚拟外键:数据库无需建立外键,只在Pirsma model中建立,支持同数据库的关联查询

  • 支持视图:在prisma model建立视图表,实现视图的查询

  • 精简数据表:简化prisma model表或字段,只声明业务需要的表或字段,缩减超图大小,提高性能

详情见 Prisma数据源 !

钩子扩展逻辑

OPERATION结合钩子能实现大部分接口,但仍有些接口无法实现,需要自行编写代码支持。

1.0版本只支持GraphQL钩子和proxy钩子,2.0版本新增了function钩子,且还解决了钩子的循环依赖问题。

修改钩子代码后,只需重启钩子,对应的数据将自动注册到Fireboom服务中。

该特性,当前只有golang钩子支持,nodejs钩子正在进行中。

GraphQL钩子

GraphQL钩子注册到Fireboom中为一种特殊的GraphQL数据源。

见上图,数据源->statistic

GraphQL示例代码
custom-go/customize/statistic.go
package customize

import (
	"custom-go/pkg/plugins"
	"fmt"

	"log"
	"time"

	"github.com/graphql-go/graphql"
)

type Feed struct {
	ID string `graphql:"id"`
}

var FeedType = graphql.NewObject(graphql.ObjectConfig{
	Name: "FeedType",
	Fields: graphql.Fields{
		"id": &graphql.Field{
			Type: graphql.ID,
		},
	},
})
var RootSubscription = graphql.NewObject(graphql.ObjectConfig{
	Name: "subscription",
	Fields: graphql.Fields{
		"feed": &graphql.Field{
			Type: FeedType,
			Resolve: func(p graphql.ResolveParams) (interface{}, error) {
				return p.Source, nil
			},
			Subscribe: func(p graphql.ResolveParams) (interface{}, error) {
				c := make(chan interface{})

				go func() {
					var i int

					for {
						i++

						feed := Feed{ID: fmt.Sprintf("%d", i)}

						select {
						case <-p.Context.Done():
							log.Println("[RootSubscription] [Subscribe] subscription canceled")
							close(c)
							return
						default:
							c <- feed
						}

						time.Sleep(250 * time.Millisecond)

						if i == 21 {
							close(c)
							return
						}
					}
				}()

				return c, nil
			},
		},
	},
})
var StatisticsSchema, _ = graphql.NewSchema(graphql.SchemaConfig{
	Query: graphql.NewObject(graphql.ObjectConfig{
		Name: "query",
		Fields: graphql.Fields{
			"GetMonthlySales": &graphql.Field{
				Type: graphql.String,
				Resolve: func(p graphql.ResolveParams) (res interface{}, err error) {
					_, _, err = plugins.ResolveArgs[any](p)
					if err != nil {
						return
					}
					return "ok", nil
				},
			},
		},
	}),
	Subscription: RootSubscription,
})

func init() {
	plugins.RegisterGraphql(&StatisticsSchema)
}

function钩子

function钩子注册到Fireboom中为一个API,且有出入参定义(json类型),此外还支持实时查询和权限控制。

见上图,API管理->function->login

function示例代码
custom-go/function/login.go
package function

import (
	"custom-go/pkg/base"
	"custom-go/pkg/plugins"
)

func init() {
	plugins.RegisterFunction[loginReq, loginRes](login)
}

type loginReq struct {
	Username string `json:"username"`
	Password string `json:"password"`
	Res      loginRes
}

type loginRes struct {
	Msg  string `json:"msg"`
	Data string `json:"data"`
}

func login(hook *base.HookRequest, body *base.OperationBody[loginReq, loginRes]) (*base.OperationBody[loginReq, loginRes], error) {
	body.Response = &base.OperationBodyResponse[loginRes]{Data: loginRes{Msg: "123"}}
	return body, nil
}

proxy钩子

proxy钩子注册到Fireboom中也为一个API,和funciton的区别是,它没有出入参定义,可以为任意类型,如非结构化数据或xml数据,同时不支持实时查询。

见上图,API管理->proxy->test

proxy示例代码
custom-go/proxy/test.go
package proxy

import (
	"custom-go/pkg/base"
	"custom-go/pkg/plugins"
	"custom-go/pkg/wgpb"
	"net/http"
)

func init() {
	plugins.RegisterProxyHook(ping)
}

var conf = &plugins.HookConfig{
	AuthRequired: true,
	AuthorizationConfig: &wgpb.OperationAuthorizationConfig{
		RoleConfig: &wgpb.OperationRoleConfig{
			RequireMatchAny: []string{"admin", "user"},
		},
	},
	EnableLiveQuery: false,
}

func ping(hook *base.HttpTransportHookRequest, body *plugins.HttpTransportBody) (*base.ClientResponse, error) {
	// do something here ...
	body.Response = &base.ClientResponse{
		StatusCode: http.StatusOK,
	}
	body.Response.OriginBody = []byte("ok")
	return body.Response, nil
}

推荐优先使用function,funciton满足不了的,再用proxy钩子。

若想使上述3个钩子生效,还需要在main.go文件中开启5-7行注释,匿名导入钩子。

custom-go/main.go
package main

import (
	// 根据需求,开启注释
	_ "custom-go/customize"
	_ "custom-go/function"
	_ "custom-go/proxy"
	"custom-go/server"
)

func main() {
	server.Execute()
}

fromclaim指令升级

1.0版本@fromClaim指令只支持枚举值,无法注入自定义的数据。

新版本新增了custom参数,从User.CustomClaims中获取数据,实现了任意数据的注入,包括 标量和数组。其入参为jsonPathComponents,填写参数路径即可。

custom-go/authentication/mutatingPostAuthentication.go
package authentication

import (
	"custom-go/pkg/base"
	"custom-go/pkg/plugins"
)

func MutatingPostAuthentication(hook *base.AuthenticationHookRequest) (*plugins.AuthenticationResponse, error) {
	// 定义自定义参数,其中key1为字符串,key2为对象
	hook.User.CustomClaims = map[string]any{
		"key1": "sss",
		"key2": map[string]string{
			"key3": "sss",
		},
	}
	return &plugins.AuthenticationResponse{User: hook.User, Status: "ok"}, nil
}
# 将User.CustomClaims的key2.key3注入到$name中
mutation MyQuery($name: String! @fromClaim(name:CUSTOM,custom: {jsonPathComponents: ["key2", "key3"]})) {
  rb_createOneT(data: {name: $name}) {
    id
    name
  }
}

事务支持

新增@transaction指令,修饰mutation OPERATION,适用于如下场景:

  • 至少有两个及以上的选择集(根字段)

  • 且必须是同一个数据库

mutation MyQuery @transaction {
  rb_createOneT(data: { name: "22211122"}) {
    id
    name
  }
  rb_createOneRole(data: {code: "a111111", name: "1111"}) {
    code
    name
  }
} 

SDK升级策略优化

稳定更新,避免过度升级

1.0版本的每次被删除后,都会从github拉取最新模板,导致过度升级。遇到破坏性更新时,钩子会报错。

因此,在sdk的json文件中增加了 gitCommitHash字段,记录模板的github hash值,保证每次都能拉取指定版本。

  "gitCommitHash": "e7fa762965b03d47057643dda8784ada625b0cee",

此外,还增加了新版本检测功能,展示是否有新版本,并基于github的对比功能,实现了新旧版本对比。

例如:https://github.com/fireboomio/sdk-template_go-server/compare/ab1427e..e7fa762

强制忽略,允许定制模板

1.0版本会对比template/[sdk-name]custom-[x]中的文件更新时间,确定是否覆盖模板文件。若用户在custom-[x]中修改模板,则每次编译都会被重新覆盖。

为了支持该特性,我们在custom-[x]中增加了.fbignore文件,语法类似.gitignore。模板生成时将忽略该文件声明的文件或目录,保证开发者修改不会被覆盖。

例如:如若修改main.go,则:

custom-go/.fbignore
# 略
main.go

环境变量优化

1.0版本的系统配置未支持环境变量,如设置->系统,不同环境迁移时,需要手动处理。

2.0版本优化了环境变量,通过环境变量可无缝迁移开发环境到生产环境。

迁移到V2.0

兼容性

1.0到2.0是一个破坏性更新,未来1.0不继续维护,但仍可以使用。

但我实在想不出,继续使用它的理由,不是吗?

迁移脚本

如果你已经有基于1.0版本项目,不用担心,我们提供了迁移脚本及教程。

您可以遵循下述仓库的教程操作,建议在开发环境下进行

仓库:https://github.com/fireboomio/fb-migration

如果有任何问题,我们将为您提供1对1指导,且免费!

文档及支持资源

当前您看到的就是2.0的文档。

2.0的文档暂未完全更新,但无需担心,只要您认真阅读 新功能和改进,基于1.0文档就可以上手2.0。

接下来,我们将逐渐更新2.0文档。

如有任何问题,可前往内测群咨询,前往->

我们非常欢迎您提出2.0的反馈意见,这将是我们持续进步的动力!

这里有两个2.0的示例项目供您参考:

RoadMap

除了 新功能和改进外,还有一些我们计划支持的新特性。也希望您 联系我们 提供更多建议。

实时协作

当前只支持离线协作,2.0计划支持实时协作,满足团队协作的需求。

  • 多人协作功能,允许团队成员同时使用和编辑同一个项目

  • 用户可以实时查看其他成员的更改,并进行实时协作和沟通,提高团队的协作效率

钩子新语言支持

当前钩子已完全支持golang,进一步优化nodejs,随后支持JAVA、Python语言!

API市场

上线API市场,集成2大类API。

  • 通用API:例如支付能力、短信验证码、邮箱发送、敏感词等通用API

  • 模型API:集成各种AI模型,如GPT、辅助编码、图片生成等

IDE优化

优化内置IDE,支持各种钩子语言的开发,包括语法提醒和在线调试。

当前可基于github codespace作为替代品,详情见 文档

AI辅助

辅助编程

基于IDE提供AI辅助编程能力,其相对于市面上同类工具最大的优势是对Fireboom钩子的特殊支持

API生成

用自然语言代替手工勾选生成OPERATION,实现API的自动生成

AI Agent

优化API文档,集成AI Agent,用自然语言实现API的编排

商业化

近日CEC-IDE事件在开发者中引起了广泛讨论,内测群也对此展开了更深入的讨论。

最终落脚点是:

从大众到企业付费意识极弱,软件繁荣不起来。表面看到的很多国外优秀开源作品,背后是人家的高GDP能保证牛奶面包可以让你去用爱发电,国外付费软件也是非常多的,开源只是一种营销手段。

——来自群友:7.

对此,我深表认同!

Fireboom作为一个还在萌芽中的技术型初创团队,一方面追求心中的月亮——以开发者为中心,另一方面又不可能离开六便士——产品商业化

从2.0开始,Fireboom将开始探索商业化。但不用担心,我们将为您提供最慷慨的免费特性,在不影响您正常项目的情况下,提供增值服务。

当前Fireboom2.0有三种版本:社区版、专业版、企业版。

社区版

其中社区版适用个人开发者,除了拥有1.0所有功能外,有如下不同:

  • API数量:100

  • 数据源数量:5

但,别担心!当项目需求超出默认限制后,可随时免费申请扩容。申请后,无限期生效!

详情填写 申请表单~

专业版

专业版适用于创业团队,拥有社区版的全部功能,且API、数据源默认无限,此外还具有如下特性:

  • 实时协作:多人编辑时,实时联动

  • 导入/导出:为项目导出API及其数据源依赖,导出插件

企业版

企业版适用于企业,拥有专业版的全部功能,此外还具有如下特性:

  • 虚拟外键:Prisma数据源,支持虚拟外键和模型精简

  • 日志监控

  • 限流熔断

  • 定时备份

  • 集群部署

  • ...

详情请前往官网 查看

如果您觉得某些政策不合理,请随时联系我们。我们将会慎重考虑您的建议!

结语

结束之际,最想感谢的是Fireboom内测群所有种子用户。是你们的使用、反馈、建议让我们走到今天!

为此,群内所有用户都将免费获得:

  1. 理由扩容 API和数据源数量至 ,且永久有效 前往申请->

  2. 理由增量编译特权1年前往申请->

1和2只需申请1个,申请2的话,自动拥有1的权限!

希望接下来的日子,仍有您的陪伴!

Fireboom团队将始终坚持“以开发者为中心”的信念,不断推陈出新,改进和提升Fireboom的功能和性能。

未来,邀您一起见证!

最后更新于