Skip to content

Commit

Permalink
Merge pull request #2 from seymourtang/main
Browse files Browse the repository at this point in the history
feat(cloudRecording):add mix recoding & individual recording support to cloud recording service
  • Loading branch information
sunshinexcode authored Apr 23, 2024
2 parents 200de8e + 4ccad9d commit bcf3881
Show file tree
Hide file tree
Showing 35 changed files with 2,235 additions and 621 deletions.
67 changes: 63 additions & 4 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,78 @@ on:
branches: [ "main" ]

jobs:
govulncheck:
runs-on: ubuntu-latest
name: govulncheck
steps:
- id: govulncheck
uses: golang/govulncheck-action@v1

golangci:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.18'
cache: false
- name: golangci-lint
uses: golangci/golangci-lint-action@v4
with:
# Require: The version of golangci-lint to use.
# When `install-mode` is `binary` (default) the value can be v1.2 or v1.2.3 or `latest` to use the latest version.
# When `install-mode` is `goinstall` the value can be v1.2.3, `latest`, or the hash of a commit.
version: v1.56.2

# Optional: working directory, useful for monorepos
# working-directory: somedir

# Optional: golangci-lint command line arguments.
#
# Note: By default, the `.golangci.yml` file should be at the root of the repository.
# The location of the configuration file can be changed by using `--config=`
args: --config=.golangci.yml

# Optional: show only new issues if it's a pull request. The default value is `false`.
# only-new-issues: true

# Optional: if set to true, then all caching functionality will be completely disabled,
# takes precedence over all other caching options.
# skip-cache: true

# Optional: if set to true, then the action won't cache or restore ~/go/pkg.
# skip-pkg-cache: true

# Optional: if set to true, then the action won't cache or restore ~/.cache/go-build.
# skip-build-cache: true

# Optional: The mode to install golangci-lint. It can be 'binary' or 'goinstall'.
# install-mode: "goinstall"


test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.18'

- name: Test
run: go test -v ./...

build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Set up Go
uses: actions/setup-go@v4
uses: actions/setup-go@v5
with:
go-version: '1.18'

- name: Test
run: go test -v ./...

- name: Build
run: go build -v ./...
6 changes: 6 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
run:
# timeout for analysis, e.g. 30s, 5m, default is 1m
timeout: 5m

# exit code when at least one issue was found, default is 1
issues-exit-code: 1
15 changes: 15 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
BASE_REGISTRY ?= docker.io/

.PHONY: lint test build

lint:
@echo ">>running lint"
@docker run --rm -t \
-v $(PWD):/app -w /app \
$(BASE_REGISTRY)golangci/golangci-lint:v1.56.2 golangci-lint -v run --config=./.golangci.yml

test:
@go test -v ./...

build:
@go build -v ./...
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Agora REST Client for Go
[![Go](https://github.com/AgoraIO-Community/agora-rest-client-go/actions/workflows/go.yml/badge.svg)](https://github.com/seymourtang/agora-rest-client-go/actions/workflows/go.yml)

`agora-rest-client-go`是用Go语言编写的一个开源项目,专门为 Agora REST API设计。它包含了 Agora 官方提供的REST API接口的包装和内部实现,可以帮助开发者更加方便的集成服务端Agora REST API。
## 特性
Expand Down
98 changes: 27 additions & 71 deletions core/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@ import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"time"
)

type Client interface {
GetAppID() string
GetLogger() Logger
DoREST(ctx context.Context, path string, method string, requestBody interface{}) (*BaseResponse, error)
}

type Config struct {
AppID string
Timeout time.Duration
Credential Credential
AppID string
HttpTimeout time.Duration
Credential Credential

RegionCode RegionArea
Logger Logger
Expand All @@ -35,16 +35,20 @@ type ClientImpl struct {
domainPool *DomainPool
}

func (c *ClientImpl) GetLogger() Logger {
return c.logger
}

var _ Client = (*ClientImpl)(nil)

const defaultTimeout = 10 * time.Second
const defaultHttpTimeout = 10 * time.Second

func NewClient(config *Config) *ClientImpl {
if config.Timeout == 0 {
config.Timeout = defaultTimeout
if config.HttpTimeout == 0 {
config.HttpTimeout = defaultHttpTimeout
}
cc := &http.Client{
Timeout: config.Timeout,
Timeout: config.HttpTimeout,
}
if config.Logger == nil {
config.Logger = defaultLogger
Expand All @@ -53,7 +57,7 @@ func NewClient(config *Config) *ClientImpl {
appID: config.AppID,
credential: config.Credential,
httpClient: cc,
timeout: config.Timeout,
timeout: config.HttpTimeout,
logger: config.Logger,
module: "http client",
domainPool: NewDomainPool(config.RegionCode, config.Logger),
Expand All @@ -72,75 +76,25 @@ func (c *ClientImpl) marshalBody(body interface{}) (io.Reader, error) {
return bytes.NewReader(jsonBody), nil
}

func (c *ClientImpl) DoREST(ctx context.Context, path string,
method string, requestBody interface{}) (*BaseResponse, error) {
timeoutCtx, cancelFunc := context.WithTimeout(ctx, c.timeout)
defer func() {
_ = cancelFunc
}()

var (
resp *BaseResponse
err error
retry int
)

err = RetryDo(func(retryCount int) error {
var doErr error

resp, doErr = c.doREST(timeoutCtx, path, method, requestBody)
if doErr != nil {
return NewRetryErr(false, doErr)
}

statusCode := resp.HttpStatusCode
switch {
case statusCode >= 200 && statusCode <= 300:
return nil
case statusCode >= 400 && statusCode < 410:
c.logger.Debugf(ctx, c.module, "http status code is %d, no retry,http response:%s", statusCode, resp.RawBody)
return &RetryErr{
false,
NewInternalErr(fmt.Sprintf("http status code is %d, no retry,http response:%s", statusCode, resp.RawBody)),
}
default:
c.logger.Debugf(ctx, c.module, "http status code is %d, retry,http response:%s", statusCode, resp.RawBody)
return fmt.Errorf("http status code is %d, retry", resp.RawBody)
}
}, func() bool {
select {
case <-ctx.Done():
return true
default:
}
return retry >= 3
}, func(i int) time.Duration {
return time.Second * time.Duration(i+1)
}, func(err error) {
c.logger.Debugf(ctx, c.module, "http request err:%s", err)
retry++
})
if resp != nil {
c.logger.Debugf(ctx, c.module, "http response:%s", resp.RawBody)
}
return resp, err
}

func (c *ClientImpl) doREST(ctx context.Context, path string,
method string, requestBody interface{}) (*BaseResponse, error) {
const doRESTTimeout = 10 * time.Second

func (c *ClientImpl) DoREST(ctx context.Context, path string,
method string, requestBody interface{},
) (*BaseResponse, error) {
var (
err error
resp *http.Response
req *http.Request
)
timeoutCtx, cancel := context.WithTimeout(ctx, doRESTTimeout)
defer cancel()

if err = c.domainPool.SelectBestDomain(ctx); err != nil {
if err = c.domainPool.SelectBestDomain(timeoutCtx); err != nil {
return nil, err
}

doHttpRequest := func() error {
req, err = c.createRequest(ctx, path, method, requestBody)
req, err = c.createRequest(timeoutCtx, path, method, requestBody)
if err != nil {
return err
}
Expand All @@ -149,12 +103,12 @@ func (c *ClientImpl) doREST(ctx context.Context, path string,
}
err = RetryDo(
func(retryCount int) error {
c.logger.Debugf(ctx, c.module, "http retry attempt:%d", retryCount)
c.logger.Debugf(timeoutCtx, c.module, "http retry attempt:%d", retryCount)
return doHttpRequest()
},
func() bool {
select {
case <-ctx.Done():
case <-timeoutCtx.Done():
return true
default:
}
Expand All @@ -167,7 +121,7 @@ func (c *ClientImpl) doREST(ctx context.Context, path string,
return 500 * time.Millisecond
},
func(err error) {
c.logger.Debugf(ctx, c.module, "http request err:%s", err)
c.logger.Debugf(timeoutCtx, c.module, "http request err:%s", err)
c.domainPool.NextRegion()
},
)
Expand All @@ -182,6 +136,7 @@ func (c *ClientImpl) doREST(ctx context.Context, path string,
if err != nil {
return nil, err
}
c.logger.Debugf(ctx, c.module, "http response:%s", body)

return &BaseResponse{
RawBody: body,
Expand All @@ -200,7 +155,8 @@ func (c *ClientImpl) GetAppID() string {
}

func (c *ClientImpl) createRequest(ctx context.Context, path string,
method string, requestBody interface{}) (*http.Request, error) {
method string, requestBody interface{},
) (*http.Request, error) {
url := c.domainPool.GetCurrentUrl() + path

c.logger.Debugf(ctx, "create request url:%s", url)
Expand Down
9 changes: 4 additions & 5 deletions core/domain.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,10 @@ type DomainPool struct {
currentRegionPrefixes []string
locker sync.Mutex

resolver DomainResolver
lastUpdate time.Time
majorDomainHasErr bool
logger Logger
module string
resolver DomainResolver
lastUpdate time.Time
logger Logger
module string
}

func NewDomainPool(domainArea RegionArea, logger Logger) *DomainPool {
Expand Down
17 changes: 8 additions & 9 deletions core/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,50 +89,49 @@ func NewDefaultLogger(level LogLevel) *sampleLogger {

func (d *sampleLogger) Debug(ctx context.Context, module string, v ...interface{}) {
if d.level <= LogDebug {
d.DEBUG.Output(2, fmt.Sprintln(v...))
_ = d.DEBUG.Output(2, fmt.Sprintln(v...))
}
}

func (d *sampleLogger) Debugf(ctx context.Context, module string, format string, v ...interface{}) {
if d.level <= LogDebug {
d.DEBUG.Output(2, fmt.Sprintf(format, v...))
_ = d.DEBUG.Output(2, fmt.Sprintf(format, v...))
}
}

func (d *sampleLogger) Error(ctx context.Context, module string, v ...interface{}) {
if d.level <= LogErr {
d.ERROR.Output(2, fmt.Sprintln(v...))
_ = d.ERROR.Output(2, fmt.Sprintln(v...))
}

}

func (d *sampleLogger) Errorf(ctx context.Context, module string, format string, v ...interface{}) {
if d.level <= LogErr {
d.ERROR.Output(2, fmt.Sprintf(format, v...))
_ = d.ERROR.Output(2, fmt.Sprintf(format, v...))
}
}

func (d *sampleLogger) Info(ctx context.Context, module string, v ...interface{}) {
if d.level >= LogInfo {
d.INFO.Output(2, fmt.Sprintln(v...))
_ = d.INFO.Output(2, fmt.Sprintln(v...))
}
}

func (d *sampleLogger) Infof(ctx context.Context, module string, format string, v ...interface{}) {
if d.level >= LogInfo {
d.WARN.Output(2, fmt.Sprintln(v...))
_ = d.WARN.Output(2, fmt.Sprintln(v...))
}
}

func (d *sampleLogger) Warn(ctx context.Context, module string, v ...interface{}) {
if d.level <= LogWarning {
d.WARN.Output(2, fmt.Sprintln(v...))
_ = d.WARN.Output(2, fmt.Sprintln(v...))
}
}

func (d *sampleLogger) Warnf(ctx context.Context, module string, format string, v ...interface{}) {
if d.level <= LogWarning {
d.WARN.Output(2, fmt.Sprintf(format, v...))
_ = d.WARN.Output(2, fmt.Sprintf(format, v...))
}
}

Expand Down
Loading

0 comments on commit bcf3881

Please sign in to comment.