Skip to content
This repository has been archived by the owner on Oct 31, 2024. It is now read-only.

Commit

Permalink
feat: annotation
Browse files Browse the repository at this point in the history
  • Loading branch information
thinkgos committed Dec 28, 2023
1 parent 6905094 commit ec963bf
Show file tree
Hide file tree
Showing 20 changed files with 633 additions and 418 deletions.
49 changes: 49 additions & 0 deletions cmd/protoc-gen-saber-asynq/annotation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package main

import (
"github.com/things-go/protogen-saber/internal/annotation"
"github.com/things-go/protogen-saber/internal/protoutil"
"google.golang.org/protobuf/compiler/protogen"
)

// annotation const value
const (
Identifier = "asynq"
Attribute_Name_Pattern = "pattern"
Attribute_Name_CronSpec = "cron_spec"
)

type Task struct {
Enabled bool
Pattern string
CronSpec string
}

func IsAnnotationTaskEnabled(s protogen.Comments) bool {
annotates, _ := protoutil.NewCommentLines(s).FindAnnotations(Identifier)
return annotates.ContainHeadless(Identifier)
}

func ParserAnnotationTask(s protogen.Comments) *Task {
ret := &Task{}
annotates, _ := protoutil.NewCommentLines(s).FindAnnotations(Identifier)
for _, annotate := range annotates {
if annotate.IsHeadless() {
ret.Enabled = true
continue
}
for _, attr := range annotate.Attrs {
switch attr.Name {
case Attribute_Name_Pattern:
if vv, ok := attr.Value.(annotation.String); ok {
ret.Pattern = vv.Value
}
case Attribute_Name_CronSpec:
if vv, ok := attr.Value.(annotation.String); ok {
ret.CronSpec = vv.Value
}
}
}
}
return ret
}
13 changes: 9 additions & 4 deletions cmd/protoc-gen-saber-asynq/asynq.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,14 @@ func genService(gen *protogen.Plugin, file *protogen.File, g *protogen.Generated
if method.Desc.IsStreamingClient() || method.Desc.IsStreamingServer() {
continue
}
rule, ok := MatchAsynqRule(method.Comments.Leading)
if ok {
sd.Methods = append(sd.Methods, buildAsynqRule(g, method, rule))
rule := ParserAnnotationTask(method.Comments.Leading)
if rule.Enabled {
if rule.Pattern != "" {
sd.Methods = append(sd.Methods, buildAsynqRule(g, method, rule))
} else {
_, _ = fmt.Fprintf(os.Stderr,
"\u001B[31mWARN\u001B[m: [file(%v) service(%v) method(%v)] enabled asynq annotation but 'Pattern' is empty.\n", file.Desc.Path(), service.GoName, method.GoName)
}
}
}
if len(sd.Methods) == 0 {
Expand All @@ -113,7 +118,7 @@ func hasHTTPRule(services []*protogen.Service) bool {
if method.Desc.IsStreamingClient() || method.Desc.IsStreamingServer() {
continue
}
if _, ok := MatchAsynqRule(method.Comments.Leading); ok {
if ok := IsAnnotationTaskEnabled(method.Comments.Leading); ok {
return true
}
}
Expand Down
36 changes: 0 additions & 36 deletions cmd/protoc-gen-saber-asynq/defined.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,7 @@
package main

import (
"github.com/things-go/protogen-saber/internal/protoutil"
"google.golang.org/protobuf/compiler/protogen"
)

const version = "v0.5.0"

// annotation const value
const (
annotation_Path = "asynq"
annotation_Key_Pattern = "pattern"
annotation_Key_CronSpec = "cron_spec"
)

type serviceDesc struct {
ServiceType string // Greeter
ServiceName string // helloworld.Greeter
Expand All @@ -31,27 +19,3 @@ type methodDesc struct {
Pattern string // 匹配器
CronSpec string // cron specification
}

type Task struct {
Pattern string
CronSpec string
}

func MatchAsynqRule(c protogen.Comments) (*Task, bool) {
annotes, _ := protoutil.NewCommentLines(c).FindAnnotation(annotation_Path)
if len(annotes) > 0 {
t := &Task{}
for _, v := range annotes {
switch v.Key {
case annotation_Key_Pattern:
t.Pattern = v.Value
case annotation_Key_CronSpec:
t.CronSpec = v.Value
}
}
if t.Pattern != "" {
return t, true
}
}
return nil, false
}
33 changes: 3 additions & 30 deletions example/asynq/asynq.asynq.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion example/asynq/asynq.proto
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ import "google/protobuf/empty.proto";

service User {
// 异步创建用户
// #[asynq(pattern="user:create")]
// #[asynq]
// #[asynq(pattern="user:create")]
rpc CreateUser(CreateUserPayload) returns (google.protobuf.Empty);
// 异步更新用户
// #[asynq]
// #[asynq(pattern="user:update")]
// #[asynq(cron_spec="@every 120s")]
rpc UpdateUser(UpdateUserPayload) returns (google.protobuf.Empty);
Expand Down
18 changes: 0 additions & 18 deletions example/seaql/dict_annote.sql

This file was deleted.

16 changes: 0 additions & 16 deletions example/seaql/dict_item_annote.sql

This file was deleted.

5 changes: 2 additions & 3 deletions example/seaql/seaql.proto
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ option java_outer_classname = "Seaql";
import "enums.proto";

// Dict 字典表
// #[seaql(name="dict")]
// #[seaql(engine="InnoDB")]
// #[seaql(charset="utf8mb4")]
// #[seaql]
// #[seaql(name="dict",engine="InnoDB",charset="utf8mb4")]
// #[seaql(index="PRIMARY KEY (`id`)")]
// #[seaql(index="UNIQUE KEY `uk_key_value` (`key`, `value`) USING BTREE")]
message Dict {
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/things-go/protogen-saber
go 1.21

require (
github.com/alecthomas/participle/v2 v2.1.1
github.com/hibiken/asynq v0.24.1
github.com/things-go/ens v0.1.0
google.golang.org/protobuf v1.32.0
Expand Down
8 changes: 8 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20O
github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/alecthomas/assert/v2 v2.3.0 h1:mAsH2wmvjsuvyBvAmCtm7zFsBlb8mIHx5ySLVdDZXL0=
github.com/alecthomas/assert/v2 v2.3.0/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ=
github.com/alecthomas/participle/v2 v2.1.1 h1:hrjKESvSqGHzRb4yW1ciisFJ4p3MGYih6icjJvbsmV8=
github.com/alecthomas/participle/v2 v2.1.1/go.mod h1:Y1+hAs8DHPmc3YUFzqllV+eSQ9ljPTk0ZkPMtEdAx2c=
github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk=
github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY=
github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
Expand Down Expand Up @@ -49,6 +55,8 @@ github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hashicorp/hcl/v2 v2.19.1 h1://i05Jqznmb2EXqa39Nsvyan2o5XyMowW5fnCKW5RPI=
github.com/hashicorp/hcl/v2 v2.19.1/go.mod h1:ThLC89FV4p9MPW804KVbe/cEXoQ8NZEh+JtMeeGErHE=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
github.com/hibiken/asynq v0.24.1 h1:+5iIEAyA9K/lcSPvx3qoPtsKJeKI5u9aOIvUmSsazEw=
github.com/hibiken/asynq v0.24.1/go.mod h1:u5qVeSbrnfT+vtG5Mq8ZPzQu/BmCKMHvTGb91uy9Tts=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
Expand Down
80 changes: 80 additions & 0 deletions internal/annotation/annotation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package annotation

import (
"github.com/alecthomas/participle/v2"
)

var parser = participle.MustBuild[Annotation](
participle.Unquote(),
participle.Union[Value](
String{}, Integer{}, Float{}, Bool{},
StringList{}, IntegerList{}, FloatList{}, BoolList{},
),
)

// Annotation an specified identifier and it's attribute list.
// `#[ident]`
// `#[ident(k1=v1,k2=v2)]`
type Annotation struct {
Identifier string `parser:"'#' '[' @Ident"`
Attrs []*NameValue `parser:"('(' (@@ (',' @@)*)? ')')?"`
Empty struct{} `parser:"']'"`
}

// `#[ident]` only, not contain any attributes.
func (a *Annotation) IsHeadless() bool {
return len(a.Attrs) == 0
}

// NameValue like `#[ident(name=value]`
type NameValue struct {
// name
Name string `parser:"@Ident '='"`
// one of follow
// String, Integer, Float, Bool,
// StringList, IntegerList, FloatList, BoolList,
Value Value `parser:"@@"`
}

// Match 匹配注解
// `#[ident]`
// `#[ident(k1=v1,k2=v2)]`
func Match(s string) (*Annotation, error) {
return parser.ParseString("", s)
}

type Annotations []*Annotation

// ContainHeadless contain headless
func (a Annotations) ContainHeadless(identifier string) bool {
for _, v := range a {
if v.Identifier == identifier && v.IsHeadless() {
return true
}
}
return false
}

func (a Annotations) Find(identifier string) Annotations {
ret := make(Annotations, 0, len(a))
for _, v := range a {
if v.Identifier == identifier {
ret = append(ret, v)
}
}
return ret
}

func (a Annotations) FindValue(identifier, name string) []Value {
ret := make([]Value, 0, len(a))
for _, v := range a {
if v.Identifier == identifier {
for _, vv := range v.Attrs {
if vv.Name == name {
ret = append(ret, vv.Value)
}
}
}
}
return ret
}
Loading

0 comments on commit ec963bf

Please sign in to comment.