Repository: vanus-labs/vanus
Pull request #453 (2023-02-23 10:04:32)

feat: add function extract_between_delimiters
### What problem does this PR solve?

Issue Number: close [#426](https://github.com/vanus-labs/vanus/issues/426)

### Problem Summary

### What is changed and how does it work?

This function creates a new json element and assign it to the string extracted between startDelimiter and endDelimiter from another json element 

### Check List

<!-- At least one of them must be included. -->

#### Tests

- [x] Unit test
- [ ] Integration test
- [ ] Manual test (add detailed scripts or steps below)
- [ ] No code


calmius: Unit test fails, I'm not sure what the problem
xdlbdy: pls resolve conflicts
codecov[bot]: # [Codecov](https://codecov.io/gh/vanus-labs/vanus/pull/453?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vanus-labs) Report
> Merging [#453](https://codecov.io/gh/vanus-labs/vanus/pull/453?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vanus-labs) (4e82004) into [main](https://codecov.io/gh/vanus-labs/vanus/commit/2a78cb5c98e21ede2d084739bfadd4151ac48054?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vanus-labs) (2a78cb5) will **decrease** coverage by `0.57%`.
> The diff coverage is `42.06%`.

<details><summary>Additional details and impacted files</summary>


[![Impacted file tree graph](https://codecov.io/gh/vanus-labs/vanus/pull/453/graphs/tree.svg?width=650&height=150&src=pr&token=RSXSIMEY4V&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vanus-labs)](https://codecov.io/gh/vanus-labs/vanus/pull/453?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vanus-labs)

```diff
@@            Coverage Diff             @@
##             main     #453      +/-   ##
==========================================
- Coverage   57.71%   57.14%   -0.57%     
==========================================
  Files         180      188       +8     
  Lines       14614    15122     +508     
==========================================
+ Hits         8434     8642     +208     
- Misses       5552     5843     +291     
- Partials      628      637       +9     
```


| [Impacted Files](https://codecov.io/gh/vanus-labs/vanus/pull/453?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vanus-labs) | Coverage Δ | |
|---|---|---|
| [...ernal/controller/trigger/validation/subscripton.go](https://codecov.io/gh/vanus-labs/vanus/pull/453?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vanus-labs#diff-aW50ZXJuYWwvY29udHJvbGxlci90cmlnZ2VyL3ZhbGlkYXRpb24vc3Vic2NyaXB0b24uZ28=) | `69.29% <ø> (+0.85%)` | :arrow_up: |
| [internal/gateway/proxy/deadletter.go](https://codecov.io/gh/vanus-labs/vanus/pull/453?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vanus-labs#diff-aW50ZXJuYWwvZ2F0ZXdheS9wcm94eS9kZWFkbGV0dGVyLmdv) | `0.00% <0.00%> (ø)` | |
| [internal/gateway/proxy/direct.go](https://codecov.io/gh/vanus-labs/vanus/pull/453?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vanus-labs#diff-aW50ZXJuYWwvZ2F0ZXdheS9wcm94eS9kaXJlY3QuZ28=) | `73.33% <0.00%> (-5.24%)` | :arrow_down: |
| [.../primitive/interceptor/memberinterceptor/member.go](https://codecov.io/gh/vanus-labs/vanus/pull/453?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vanus-labs#diff-aW50ZXJuYWwvcHJpbWl0aXZlL2ludGVyY2VwdG9yL21lbWJlcmludGVyY2VwdG9yL21lbWJlci5nbw==) | `0.00% <0.00%> (ø)` | |
| [internal/store/io/file\_linux.go](https://codecov.io/gh/vanus-labs/vanus/pull/453?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vanus-labs#diff-aW50ZXJuYWwvc3RvcmUvaW8vZmlsZV9saW51eC5nbw==) | `0.00% <0.00%> (ø)` | |
| [internal/store/io/zone/segmentedfile/recovery.go](https://codecov.io/gh/vanus-labs/vanus/pull/453?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vanus-labs#diff-aW50ZXJuYWwvc3RvcmUvaW8vem9uZS9zZWdtZW50ZWRmaWxlL3JlY292ZXJ5Lmdv) | `18.98% <0.00%> (ø)` | |
| [internal/store/raft/block/executor.go](https://codecov.io/gh/vanus-labs/vanus/pull/453?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vanus-labs#diff-aW50ZXJuYWwvc3RvcmUvcmFmdC9ibG9jay9leGVjdXRvci5nbw==) | `0.00% <0.00%> (ø)` | |
| [internal/store/segment/server.go](https://codecov.io/gh/vanus-labs/vanus/pull/453?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vanus-labs#diff-aW50ZXJuYWwvc3RvcmUvc2VnbWVudC9zZXJ2ZXIuZ28=) | `14.10% <0.00%> (-0.03%)` | :arrow_down: |
| [internal/store/vsb/engine\_open.go](https://codecov.io/gh/vanus-labs/vanus/pull/453?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vanus-labs#diff-aW50ZXJuYWwvc3RvcmUvdnNiL2VuZ2luZV9vcGVuLmdv) | `2.98% <0.00%> (+0.12%)` | :arrow_up: |
| [internal/store/wal/recovery.go](https://codecov.io/gh/vanus-labs/vanus/pull/453?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vanus-labs#diff-aW50ZXJuYWwvc3RvcmUvd2FsL3JlY292ZXJ5Lmdv) | `57.14% <0.00%> (-2.51%)` | :arrow_down: |
| ... and [49 more](https://codecov.io/gh/vanus-labs/vanus/pull/453?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vanus-labs) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/vanus-labs/vanus/pull/453?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vanus-labs).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vanus-labs)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/vanus-labs/vanus/pull/453?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vanus-labs). Last update [474445a...4e82004](https://codecov.io/gh/vanus-labs/vanus/pull/453?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vanus-labs). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vanus-labs).

</details>
xdlbdy: pls resolve golangci-lint  error

Patch:
diff --git a/Makefile b/Makefile
index ee39669..7219db8 100644
--- a/Makefile
+++ b/Makefile
@@ -55,6 +55,9 @@ t3=${t2} -X 'main.BuildDate=${DATE}'
 t4=${t3} -X 'main.GoVersion=${GO_VERSION}'
 LD_FLAGS=${t4} -X 'main.Platform=${GOOS}/${GOARCH}'
 
+docker-push-toolbox:
+	docker buildx build --no-cache --platform ${DOCKER_PLATFORM} -t ${DOCKER_REPO}/toolbox:${IMAGE_TAG} -f build/toolbox/Dockerfile . --push
+
 build-cmd:
 	$(GO_BUILD)  -ldflags "${LD_FLAGS}" -o bin/vsctl ./vsctl/
 
diff --git a/build/all-in-one/Dockerfile b/build/all-in-one/Dockerfile
index e44b207..512b6e7 100644
--- a/build/all-in-one/Dockerfile
+++ b/build/all-in-one/Dockerfile
@@ -15,7 +15,7 @@ RUN GOOS=$TARGETOS GOARCH=$TARGETARCH make build-timer
 RUN GOOS=$TARGETOS GOARCH=$TARGETARCH make build-gateway
 
 
-FROM ubuntu:22.04
+FROM --platform=$BUILDPLATFORM ubuntu:22.10
 WORKDIR /vanus
 
 ARG VERSION
diff --git a/build/images/controller/Dockerfile b/build/images/controller/Dockerfile
index a97d469..139624f 100644
--- a/build/images/controller/Dockerfile
+++ b/build/images/controller/Dockerfile
@@ -8,7 +8,7 @@ ARG TARGETOS
 ARG TARGETARCH
 RUN GOOS=$TARGETOS GOARCH=$TARGETARCH make build-controller
 
-FROM ubuntu:22.10
+FROM --platform=$BUILDPLATFORM ubuntu:22.10
 WORKDIR /vanus
 COPY --from=builder /workspace/bin/controller bin/controller
 ENTRYPOINT ["bin/controller"]
diff --git a/build/images/gateway/Dockerfile b/build/images/gateway/Dockerfile
index c335f78..2d9817b 100644
--- a/build/images/gateway/Dockerfile
+++ b/build/images/gateway/Dockerfile
@@ -8,7 +8,7 @@ ARG TARGETOS
 ARG TARGETARCH
 RUN GOOS=$TARGETOS GOARCH=$TARGETARCH make build-gateway
 
-FROM ubuntu:22.10
+FROM --platform=$BUILDPLATFORM ubuntu:22.10
 WORKDIR /vanus
 COPY --from=builder /workspace/bin/gateway bin/gateway
 ENTRYPOINT ["bin/gateway"]
diff --git a/build/images/root-controller/Dockerfile b/build/images/root-controller/Dockerfile
index 50a91b3..c15942d 100644
--- a/build/images/root-controller/Dockerfile
+++ b/build/images/root-controller/Dockerfile
@@ -8,7 +8,7 @@ ARG TARGETOS
 ARG TARGETARCH
 RUN GOOS=$TARGETOS GOARCH=$TARGETARCH make build-root
 
-FROM ubuntu:22.10
+FROM --platform=$BUILDPLATFORM ubuntu:22.10
 WORKDIR /vanus
 COPY --from=builder /workspace/bin/root-controller bin/root-controller
 ENTRYPOINT ["bin/root-controller"]
diff --git a/build/images/store/Dockerfile b/build/images/store/Dockerfile
index cc33f6d..183badb 100644
--- a/build/images/store/Dockerfile
+++ b/build/images/store/Dockerfile
@@ -8,7 +8,7 @@ ARG TARGETOS
 ARG TARGETARCH
 RUN GOOS=$TARGETOS GOARCH=$TARGETARCH make build-store
 
-FROM ubuntu:22.10
+FROM --platform=$BUILDPLATFORM ubuntu:22.10
 WORKDIR /vanus
 COPY --from=builder /workspace/bin/store bin/store
 ENTRYPOINT ["bin/store"]
diff --git a/build/images/timer/Dockerfile b/build/images/timer/Dockerfile
index e67ede6..a4a583a 100644
--- a/build/images/timer/Dockerfile
+++ b/build/images/timer/Dockerfile
@@ -8,7 +8,7 @@ ARG TARGETOS
 ARG TARGETARCH
 RUN GOOS=$TARGETOS GOARCH=$TARGETARCH make build-timer
 
-FROM ubuntu:22.10
+FROM --platform=$BUILDPLATFORM ubuntu:22.10
 WORKDIR /vanus
 COPY --from=builder /workspace/bin/timer bin/timer
 ENTRYPOINT ["bin/timer"]
diff --git a/build/images/trigger/Dockerfile b/build/images/trigger/Dockerfile
index 9b45b92..3717267 100644
--- a/build/images/trigger/Dockerfile
+++ b/build/images/trigger/Dockerfile
@@ -8,7 +8,7 @@ ARG TARGETOS
 ARG TARGETARCH
 RUN GOOS=$TARGETOS GOARCH=$TARGETARCH make build-trigger
 
-FROM ubuntu:22.10
+FROM --platform=$BUILDPLATFORM ubuntu:22.10
 WORKDIR /vanus
 COPY --from=builder /workspace/bin/trigger bin/trigger
 ENTRYPOINT ["bin/trigger"]
diff --git a/build/toolbox/Dockerfile b/build/toolbox/Dockerfile
new file mode 100644
index 0000000..cc68771
--- /dev/null
+++ b/build/toolbox/Dockerfile
@@ -0,0 +1,29 @@
+FROM --platform=$BUILDPLATFORM ubuntu:22.10
+
+ARG TARGETOS
+ARG TARGETARCH
+
+WORKDIR /vanus/toolbox
+
+RUN apt update -y && apt upgrade -y
+# install tools
+RUN apt install -y wget curl ncat vim
+
+# install etcdctl
+RUN wget https://github.com/etcd-io/etcd/releases/download/v3.5.7/etcd-v3.5.7-$TARGETOS-$TARGETARCH.tar.gz
+RUN tar -xzvf etcd-v3.5.7-$TARGETOS-$TARGETARCH.tar.gz
+
+# install vsctl
+RUN wget https://dl.vanus.ai/vsctl/latest/$TARGETOS-$TARGETARCH/vsctl
+
+# mv to /vanus/toolbox/bin
+RUN mkdir -p /vanus/toolbox/bin
+RUN mv etcd-v3.5.7-$TARGETOS-$TARGETARCH/etcdctl /vanus/toolbox/bin
+RUN mv vsctl /vanus/toolbox/bin
+RUN chmod a+x /vanus/toolbox/bin/*
+
+# clean
+RUN rm -rf etcd-v3.5.7-$TARGETOS-$TARGETARCH.*
+
+RUN echo 'alias vsctl="vsctl --endpoint vanus-gateway:8080 --operator-endpoint vanus-operator:8089"' >> /root/.bashrc
+ENV PATH=$PATH:/vanus/toolbox/etcd:/vanus/toolbox/bin
\ No newline at end of file
diff --git a/internal/controller/eventbus/controller.go b/internal/controller/eventbus/controller.go
index a0ec837..0595eb9 100644
--- a/internal/controller/eventbus/controller.go
+++ b/internal/controller/eventbus/controller.go
@@ -240,6 +240,17 @@ func (ctrl *controller) createEventbus(
 			" maximum is %d", maximumEventlogNum))
 	}
 
+	pb, err := ctrl.GetEventbusWithHumanFriendly(ctx, &ctrlpb.GetEventbusWithHumanFriendlyRequest{
+		NamespaceId:  req.NamespaceId,
+		EventbusName: req.Name,
+	})
+	if err != nil && !errors.Is(err, errors.ErrResourceNotFound) {
+		return nil, err
+	}
+	if pb != nil {
+		return nil, errors.ErrResourceAlreadyExist.WithMessage("the eventbus already exists")
+	}
+
 	id, err := vanus.NewID()
 	if err != nil {
 		log.Warning(ctx, "failed to create eventbus ID", map[string]interface{}{
diff --git a/internal/gateway/gateway.go b/internal/gateway/gateway.go
index 9ed1229..14ce849 100644
--- a/internal/gateway/gateway.go
+++ b/internal/gateway/gateway.go
@@ -18,8 +18,6 @@ import (
 	"context"
 	"errors"
 	"fmt"
-	"github.com/vanus-labs/vanus/pkg/cluster"
-	"google.golang.org/grpc/credentials/insecure"
 	"net"
 	"net/http"
 	"strings"
@@ -29,11 +27,14 @@ import (
 	"github.com/cloudevents/sdk-go/v2/protocol"
 	cehttp "github.com/cloudevents/sdk-go/v2/protocol/http"
 	"go.opentelemetry.io/otel/trace"
+	"google.golang.org/grpc/credentials/insecure"
 
 	"github.com/vanus-labs/vanus/internal/gateway/proxy"
+	"github.com/vanus-labs/vanus/internal/primitive"
 	"github.com/vanus-labs/vanus/internal/primitive/vanus"
 	"github.com/vanus-labs/vanus/observability/log"
 	"github.com/vanus-labs/vanus/observability/tracing"
+	"github.com/vanus-labs/vanus/pkg/cluster"
 	"github.com/vanus-labs/vanus/proto/pkg/cloudevents"
 	"github.com/vanus-labs/vanus/proto/pkg/codec"
 	proxypb "github.com/vanus-labs/vanus/proto/pkg/proxy"
@@ -128,25 +129,43 @@ func (ga *ceGateway) receive(ctx context.Context, event v2.Event) (re *v2.Event,
 	return re, v2.ResultACK
 }
 
+const (
+	httpRequestPrefix = "/gateway"
+)
+
 func (ga *ceGateway) getEventbusFromPath(ctx context.Context, reqData *cehttp.RequestData) (vanus.ID, error) {
-	// namespaces/:namespace_name/eventbus/:eventbus_name/events
-	path := strings.TrimLeft(reqData.URL.String(), "/")
-	strs := strings.Split(path, "/")
-	if len(strs) != 5 {
-		return 0, errors.New("invalid request path")
-	}
-	if strs[0] != "namespaces" && strs[2] != "eventbus" && strs[4] != "events" {
-		return 0, errors.New("invalid request path")
+	// TODO validate
+	reqPathStr := reqData.URL.String()
+	var (
+		ns   string
+		name string
+	)
+	if strings.HasPrefix(reqPathStr, httpRequestPrefix) { // Deprecated, just for compatibility of older than v0.7.0
+		ns = primitive.DefaultNamespace
+		name = strings.TrimLeft(reqPathStr[len(httpRequestPrefix):], "/")
+	} else {
+		// namespaces/:namespace_name/eventbus/:eventbus_name/events
+		path := strings.TrimLeft(reqData.URL.String(), "/")
+		strs := strings.Split(path, "/")
+		if len(strs) != 5 {
+			return 0, errors.New("invalid request path")
+		}
+		if strs[0] != "namespaces" && strs[2] != "eventbus" && strs[4] != "events" {
+			return 0, errors.New("invalid request path")
+		}
+		ns = strs[1]
+		name = strs[3]
 	}
-	if strs[1] == "" {
+
+	if ns == "" {
 		return 0, errors.New("namespace is empty")
 	}
 
-	if strs[3] == "" {
+	if name == "" {
 		return 0, errors.New("eventbus is empty")
 	}
 
-	eb, err := ga.ctrl.EventbusService().GetEventbusByName(ctx, strs[1], strs[3])
+	eb, err := ga.ctrl.EventbusService().GetEventbusByName(ctx, ns, name)
 	if err != nil {
 		return 0, err
 	}
diff --git a/internal/primitive/transform/action/strings/extract_between_delimiters.go b/internal/primitive/transform/action/strings/extract_between_delimiters.go
new file mode 100644
index 0000000..7234bba
--- /dev/null
+++ b/internal/primitive/transform/action/strings/extract_between_delimiters.go
@@ -0,0 +1,73 @@
+// Copyright 2023 Linkall 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.
+
+package strings
+
+import (
+	"fmt"
+	"strings"
+
+	"github.com/vanus-labs/vanus/internal/primitive/transform/action"
+	"github.com/vanus-labs/vanus/internal/primitive/transform/arg"
+	"github.com/vanus-labs/vanus/internal/primitive/transform/common"
+	"github.com/vanus-labs/vanus/internal/primitive/transform/context"
+)
+
+type ExtractBetweenDelimitersAction struct {
+	action.CommonAction
+}
+
+// NewExtractBetweenDelimitersAction [sourceJSONPath, targetJSONPath, startDelimiter, endDelimiter].
+func NewExtractBetweenDelimitersAction() action.Action {
+	return &ExtractBetweenDelimitersAction{
+		CommonAction: action.CommonAction{
+			ActionName: "EXTRACT_BETWEEN_DELIMITERS",
+			FixedArgs:  []arg.TypeList{arg.EventList, arg.EventList, arg.All, arg.All},
+		},
+	}
+}
+
+func (a *ExtractBetweenDelimitersAction) Init(args []arg.Arg) error {
+	a.TargetArg = args[1]
+	a.Args = args[:1]
+	a.Args = append(a.Args, args[2:]...)
+	a.ArgTypes = []common.Type{common.String, common.String, common.String}
+	return nil
+}
+
+func (a *ExtractBetweenDelimitersAction) Execute(ceCtx *context.EventContext) error {
+	args, err := a.RunArgs(ceCtx)
+	if err != nil {
+		return err
+	}
+	sourceJSONPath, _ := args[0].(string)
+	startDelimiter, _ := args[1].(string)
+	endDelimiter, _ := args[2].(string)
+
+	if startDelimiter == "" || endDelimiter == "" {
+		return fmt.Errorf("start or end delimiter is empty")
+	}
+	startIndex := strings.Index(sourceJSONPath, startDelimiter)
+	if startIndex < 0 {
+		return fmt.Errorf("start delemiter is not exist")
+	}
+	startIndex += len(startDelimiter)
+	endIndex := strings.Index(sourceJSONPath[startIndex:], endDelimiter)
+	if endIndex < 0 {
+		return fmt.Errorf("end delemiter is not exist")
+	}
+	endIndex += startIndex
+	newValue := sourceJSONPath[startIndex:endIndex]
+	return a.TargetArg.SetValue(ceCtx, newValue)
+}
diff --git a/internal/primitive/transform/runtime/init.go b/internal/primitive/transform/runtime/init.go
index 424a2a3..c31b2b6 100644
--- a/internal/primitive/transform/runtime/init.go
+++ b/internal/primitive/transform/runtime/init.go
@@ -53,6 +53,7 @@ func init() {
 		strings.NewReplaceBetweenPositionsAction,
 		strings.NewCapitalizeSentenceAction,
 		strings.NewCheckCustomValuesAction,
+		strings.NewExtractBetweenDelimitersAction,
 		strings.NewExtractMissingAction,
 		strings.NewReplaceBetweenDelimitersAction,
 		strings.NewCapitalizeWordAction,
diff --git a/pkg/cluster/eventbus.go b/pkg/cluster/eventbus.go
index 5f5cf47..cdb912f 100644
--- a/pkg/cluster/eventbus.go
+++ b/pkg/cluster/eventbus.go
@@ -6,12 +6,11 @@ import (
 	"strings"
 	"sync"
 
-	"google.golang.org/protobuf/types/known/wrapperspb"
-
 	"github.com/vanus-labs/vanus/pkg/cluster/raw_client"
 	"github.com/vanus-labs/vanus/pkg/errors"
 	ctrlpb "github.com/vanus-labs/vanus/proto/pkg/controller"
 	"github.com/vanus-labs/vanus/proto/pkg/meta"
+	"google.golang.org/protobuf/types/known/wrapperspb"
 )
 
 var (
@@ -55,7 +54,7 @@ func (es *eventbusService) GetEventbusByName(ctx context.Context, ns, name strin
 		return nil, err
 	}
 
-	es.cache.Store(key, eb)
+	// es.cache.Store(key, eb) unmask when dirty cache is resolved
 	return eb, nil
 }
 
@@ -70,7 +69,7 @@ func (es *eventbusService) GetEventbus(ctx context.Context, id uint64) (*meta.Ev
 		return nil, err
 	}
 
-	es.cache.Store(id, eb)
+	// es.cache.Store(id, eb) unmask when dirty cache is resolved
 	return eb, nil
 }
 
diff --git a/pkg/cluster/mock_controller.go b/pkg/cluster/mock_controller.go
index d9aa4d1..99e9bb1 100644
--- a/pkg/cluster/mock_controller.go
+++ b/pkg/cluster/mock_controller.go
@@ -216,6 +216,21 @@ func (mr *MockNamespaceServiceMockRecorder) GetNamespace(ctx, id interface{}) *g
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNamespace", reflect.TypeOf((*MockNamespaceService)(nil).GetNamespace), ctx, id)
 }
 
+// GetNamespaceByName mocks base method.
+func (m *MockNamespaceService) GetNamespaceByName(ctx context.Context, name string) (*meta.Namespace, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "GetNamespaceByName", ctx, name)
+	ret0, _ := ret[0].(*meta.Namespace)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// GetNamespaceByName indicates an expected call of GetNamespaceByName.
+func (mr *MockNamespaceServiceMockRecorder) GetNamespaceByName(ctx, name interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNamespaceByName", reflect.TypeOf((*MockNamespaceService)(nil).GetNamespaceByName), ctx, name)
+}
+
 // GetSystemNamespace mocks base method.
 func (m *MockNamespaceService) GetSystemNamespace(ctx context.Context) (*meta.Namespace, error) {
 	m.ctrl.T.Helper()
@@ -312,33 +327,34 @@ func (mr *MockEventbusServiceMockRecorder) GetEventbus(ctx, id interface{}) *gom
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEventbus", reflect.TypeOf((*MockEventbusService)(nil).GetEventbus), ctx, id)
 }
 
-// GetSystemEventbusByName mocks base method.
-func (m *MockEventbusService) GetSystemEventbusByName(ctx context.Context, name string) (*meta.Eventbus, error) {
+// GetEventbusByName mocks base method.
+func (m *MockEventbusService) GetEventbusByName(ctx context.Context, ns, name string) (*meta.Eventbus, error) {
 	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "GetSystemEventbusByName", ctx, name)
+	ret := m.ctrl.Call(m, "GetEventbusByName", ctx, ns, name)
 	ret0, _ := ret[0].(*meta.Eventbus)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
 
-// GetSystemEventbusByName indicates an expected call of GetSystemEventbusByName.
-func (mr *MockEventbusServiceMockRecorder) GetSystemEventbusByName(ctx, name interface{}) *gomock.Call {
+// GetEventbusByName indicates an expected call of GetEventbusByName.
+func (mr *MockEventbusServiceMockRecorder) GetEventbusByName(ctx, ns, name interface{}) *gomock.Call {
 	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSystemEventbusByName", reflect.TypeOf((*MockEventbusService)(nil).GetSystemEventbusByName), ctx, name)
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEventbusByName", reflect.TypeOf((*MockEventbusService)(nil).GetEventbusByName), ctx, ns, name)
 }
 
-// IsExist mocks base method.
-func (m *MockEventbusService) IsExist(ctx context.Context, id uint64) bool {
+// GetSystemEventbusByName mocks base method.
+func (m *MockEventbusService) GetSystemEventbusByName(ctx context.Context, name string) (*meta.Eventbus, error) {
 	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "IsExist", ctx, id)
-	ret0, _ := ret[0].(bool)
-	return ret0
+	ret := m.ctrl.Call(m, "GetSystemEventbusByName", ctx, name)
+	ret0, _ := ret[0].(*meta.Eventbus)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
 }
 
-// IsExist indicates an expected call of IsExist.
-func (mr *MockEventbusServiceMockRecorder) IsExist(ctx, id interface{}) *gomock.Call {
+// GetSystemEventbusByName indicates an expected call of GetSystemEventbusByName.
+func (mr *MockEventbusServiceMockRecorder) GetSystemEventbusByName(ctx, name interface{}) *gomock.Call {
 	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsExist", reflect.TypeOf((*MockEventbusService)(nil).IsExist), ctx, id)
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSystemEventbusByName", reflect.TypeOf((*MockEventbusService)(nil).GetSystemEventbusByName), ctx, name)
 }
 
 // RawClient mocks base method.
diff --git a/pkg/cluster/namespace.go b/pkg/cluster/namespace.go
index e79be84..a9c147c 100644
--- a/pkg/cluster/namespace.go
+++ b/pkg/cluster/namespace.go
@@ -43,7 +43,7 @@ func (ns *namespaceService) GetNamespace(ctx context.Context, id uint64) (*metap
 	if err != nil {
 		return nil, err
 	}
-	ns.cache.Store(id, n)
+	// ns.cache.Store(id, n) unmask when dirty cache is resolved
 	return n, nil
 }
 
@@ -64,7 +64,7 @@ func (ns *namespaceService) GetNamespaceByName(ctx context.Context, name string)
 	if err != nil {
 		return nil, err
 	}
-	ns.cache.Store(name, n)
+	// ns.cache.Store(name, n) unmask when dirty cache is resolved
 	return n, nil
 }
 


Test patch:
diff --git a/internal/gateway/gateway_test.go b/internal/gateway/gateway_test.go
index 76d4750..3b51c8c 100644
--- a/internal/gateway/gateway_test.go
+++ b/internal/gateway/gateway_test.go
@@ -16,11 +16,9 @@ package gateway
 
 import (
 	"context"
-	"errors"
 	"fmt"
 	"math/rand"
 	"net/url"
-	"strconv"
 	"testing"
 	"time"
 
@@ -32,8 +30,9 @@ import (
 
 	"github.com/vanus-labs/vanus/client"
 	"github.com/vanus-labs/vanus/client/pkg/api"
-	"github.com/vanus-labs/vanus/internal/primitive"
 	"github.com/vanus-labs/vanus/internal/primitive/vanus"
+	"github.com/vanus-labs/vanus/pkg/cluster"
+	metapb "github.com/vanus-labs/vanus/proto/pkg/meta"
 )
 
 func TestGateway_NewGateway(t *testing.T) {
@@ -83,19 +82,19 @@ func TestGateway_receive(t *testing.T) {
 		So(ret, ShouldBeError)
 	})
 
-	Convey("test receive failure2", t, func() {
-		e := ce.NewEvent()
-		reqData := &cehttp.RequestData{
-			URL: &url.URL{
-				Opaque: "/gateway/test",
-			},
-		}
-		e.SetExtension(primitive.XVanusDeliveryTime, "2006-01-02T15:04:05")
-		stub := StubFunc(&requestDataFromContext, reqData)
-		defer stub.Reset()
-		_, ret := ga.receive(ctx, e)
-		So(ret, ShouldBeError)
-	})
+	// Convey("test receive failure2", t, func() {
+	//	e := ce.NewEvent()
+	//	reqData := &cehttp.RequestData{
+	//		URL: &url.URL{
+	//			Opaque: "/gateway/test",
+	//		},
+	//	}
+	//	e.SetExtension(primitive.XVanusDeliveryTime, "2006-01-02T15:04:05")
+	//	stub := StubFunc(&requestDataFromContext, reqData)
+	//	defer stub.Reset()
+	//	_, ret := ga.receive(ctx, e)
+	//	So(ret, ShouldBeError)
+	// })
 
 	// Convey("test receive failure3", t, func() {
 	// 	e := ce.NewEvent()
@@ -116,25 +115,68 @@ func TestGateway_receive(t *testing.T) {
 }
 
 func TestGateway_getEventbusFromPath(t *testing.T) {
-	Convey("test get eventbus from path return nil ", t, func() {
+	ga := &ceGateway{}
+	Convey("invalid request path", t, func() {
 		reqData := &cehttp.RequestData{
 			URL: &url.URL{
-				Opaque: "/test",
+				Opaque: "/a/b/c/d",
+			},
+		}
+		_, err := ga.getEventbusFromPath(context.Background(), reqData)
+		So(err.Error(), ShouldEqual, "invalid request path")
+
+		reqData = &cehttp.RequestData{
+			URL: &url.URL{
+				Opaque: "/ns/b/eb/d",
 			},
 		}
-		_, err := getEventbusFromPath(context.Background(), reqData)
-		So(errors.Is(err, strconv.ErrSyntax), ShouldBeTrue)
+		_, err = ga.getEventbusFromPath(context.Background(), reqData)
+		So(err.Error(), ShouldEqual, "invalid request path")
 	})
+
+	Convey("test namespace or eventbus is empty", t, func() {
+		reqData := &cehttp.RequestData{
+			URL: &url.URL{
+				Opaque: "/namespaces//eventbus/test/events",
+			},
+		}
+		_, err := ga.getEventbusFromPath(context.Background(), reqData)
+		So(err.Error(), ShouldEqual, "namespace is empty")
+
+		reqData = &cehttp.RequestData{
+			URL: &url.URL{
+				Opaque: "/namespaces/default/eventbus//events",
+			},
+		}
+		_, err = ga.getEventbusFromPath(context.Background(), reqData)
+		So(err.Error(), ShouldEqual, "eventbus is empty")
+	})
+
+	ctrl := NewController(t)
+	cctrl := cluster.NewMockCluster(ctrl)
+	ebSvc := cluster.NewMockEventbusService(ctrl)
+	cctrl.EXPECT().EventbusService().AnyTimes().Return(ebSvc)
+
+	ebID := vanus.NewTestID().Uint64()
+	ebSvc.EXPECT().GetEventbusByName(Any(), "default", "test").Times(1).Return(
+		&metapb.Eventbus{
+			Name:        "test",
+			LogNumber:   1,
+			Id:          ebID,
+			Description: "desc",
+			NamespaceId: vanus.NewTestID().Uint64(),
+		}, nil)
+	ga.ctrl = cctrl
 	Convey("test get eventbus from path return path ", t, func() {
-		vid := vanus.NewTestID()
 		reqData := &cehttp.RequestData{
 			URL: &url.URL{
-				Opaque: fmt.Sprintf("/%s", vid.String()),
+				Opaque: "/namespaces/default/eventbus/test/events",
 			},
 		}
-		id, err := getEventbusFromPath(context.Background(), reqData)
+
+		id, err := ga.getEventbusFromPath(context.Background(), reqData)
 		So(err, ShouldBeNil)
-		So(id, ShouldEqual, vid)
+		So(id, ShouldEqual, ebID)
 	})
 }
 
diff --git a/internal/primitive/transform/action/strings/extract_between_delimiters_test.go b/internal/primitive/transform/action/strings/extract_between_delimiters_test.go
new file mode 100644
index 0000000..d42c6d9
--- /dev/null
+++ b/internal/primitive/transform/action/strings/extract_between_delimiters_test.go
@@ -0,0 +1,58 @@
+// Copyright 2023 Linkall 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.
+
+package strings_test
+
+import (
+	"testing"
+
+	cetest "github.com/cloudevents/sdk-go/v2/test"
+	"github.com/vanus-labs/vanus/internal/primitive/transform/action/strings"
+	"github.com/vanus-labs/vanus/internal/primitive/transform/context"
+	"github.com/vanus-labs/vanus/internal/primitive/transform/runtime"
+	. "github.com/smartystreets/goconvey/convey"
+)
+
+func TestExtractBetweenDelimitersAction(t *testing.T) {
+	funcName := strings.NewExtractBetweenDelimitersAction().Name()
+	Convey("test Positive testcase", t, func() {
+		a, err := runtime.NewAction([]interface{}{funcName, "$.test", "$.data.target", "&&", "&"})
+		So(err, ShouldBeNil)
+		e := cetest.MinEvent()
+		data := map[string]interface{}{}
+		e.SetExtension("test", "Hi welcome to &&Vanus&")
+		ceCtx := &context.EventContext{
+			Event: &e,
+			Data:  data,
+		}
+		err = a.Execute(ceCtx)
+		So(err, ShouldBeNil)
+		res, ok := data["target"]
+		So(ok, ShouldBeTrue)
+		So(res, ShouldEqual, "Vanus")
+	})
+	Convey("test Negative: Only one delimiter is present in the string testcase", t, func() {
+		a, err := runtime.NewAction([]interface{}{funcName, "$.test", "$.data.target", "&", "&"}) 
+		So(err, ShouldBeNil)
+		e := cetest.MinEvent()
+		data := map[string]interface{}{}
+		e.SetExtension("test", "Hi welcome to &Vanus friend")
+		ceCtx := &context.EventContext{
+			Event: &e,
+			Data:  data,
+		}
+		err = a.Execute(ceCtx)
+		So(err.Error(), ShouldEqual, "end delemiter is not exist")
+	})
+}
diff --git a/internal/timer/timingwheel/timingwheel_test.go b/internal/timer/timingwheel/timingwheel_test.go
index 2b1e325..4d4d6f8 100644
--- a/internal/timer/timingwheel/timingwheel_test.go
+++ b/internal/timer/timingwheel/timingwheel_test.go
@@ -93,7 +93,6 @@ func TestTimingWheel_Start(t *testing.T) {
 		mockSvc.EXPECT().GetSystemEventbusByName(Any(), Any()).AnyTimes().Return(&meta.Eventbus{
 			Id: 0,
 		}, nil)
-		mockSvc.EXPECT().IsExist(Any(), Any()).AnyTimes().Return(true)
 
 		Convey("test timingwheel start bucket start success", func() {
 			tw.SetLeader(false)
@@ -160,7 +159,6 @@ func TestTimingWheel_IsDeployed(t *testing.T) {
 		tw.ctrl = mockCl
 		mockSvc := cluster.NewMockEventbusService(mockCtrl)
 		mockCl.EXPECT().EventbusService().AnyTimes().Return(mockSvc)
-		mockSvc.EXPECT().IsExist(Any(), Any()).AnyTimes().Return(true)
 		mockSvc.EXPECT().GetSystemEventbusByName(Any(), Any()).AnyTimes().Return(&meta.Eventbus{
 			Id: 0,
 		}, nil)