qdy 3 месяцев назад
Родитель
Сommit
b5bf99e5e1
6 измененных файлов: 265 добавлений и 1 удалений
  1. 0
    0
      factory/db_factory.go
  2. 105
    0
      factory/doris_factory.go
  3. 48
    0
      factory/http_factory.go
  4. 103
    0
      factory/redis_factory.go
  5. 1
    1
      go.mod
  6. 8
    0
      go.sum

factory/factory.go → factory/db_factory.go Просмотреть файл


+ 105
- 0
factory/doris_factory.go Просмотреть файл

@@ -0,0 +1,105 @@
1
+package factory
2
+
3
+import (
4
+	"encoding/json"
5
+	"fmt"
6
+	"io"
7
+	"net/http"
8
+	"strings"
9
+	"time"
10
+
11
+	"git.x2erp.com/qdy/go-base/config"
12
+)
13
+
14
+// DorisFactory Doris HTTP客户端工厂
15
+type DorisFactory struct {
16
+	config     config.IConfig
17
+	httpClient *http.Client
18
+}
19
+
20
+// NewDorisFactory 创建Doris HTTP客户端工厂
21
+func NewDorisFactory(httpFactory *HTTPFactory) (*DorisFactory, error) {
22
+	cfg := config.GetConfig()
23
+
24
+	if err := config.GetInitError(); err != nil {
25
+		return nil, fmt.Errorf("failed to load config: %v", err)
26
+	}
27
+
28
+	if !cfg.IsDorisConfigured() {
29
+		return nil, fmt.Errorf("doris configuration is incomplete")
30
+	}
31
+
32
+	return &DorisFactory{
33
+		config:     cfg,
34
+		httpClient: httpFactory.CreateHTTPClient(),
35
+	}, nil
36
+}
37
+
38
+// CreateDorisClient 创建Doris HTTP客户端
39
+func (f *DorisFactory) CreateDorisClient() *DorisClient {
40
+	dorisConfig := f.config.GetDoris()
41
+
42
+	return &DorisClient{
43
+		httpClient: f.httpClient,
44
+		FEHost:     dorisConfig.FEHost,
45
+		FEPort:     dorisConfig.FEPort,
46
+		Username:   dorisConfig.FEUsername,
47
+		Password:   dorisConfig.FEPassword,
48
+		Timeout:    time.Duration(dorisConfig.StreamLoadTimeout) * time.Second,
49
+	}
50
+}
51
+
52
+// DorisClient Doris HTTP客户端
53
+type DorisClient struct {
54
+	httpClient *http.Client
55
+	FEHost     string
56
+	FEPort     int
57
+	Username   string
58
+	Password   string
59
+	Timeout    time.Duration
60
+}
61
+
62
+// InsertCSV 插入CSV数据到Doris 只认数据次序
63
+func (c *DorisClient) DorisInsertCSV(database, table, csvData string, skipHeader bool) error {
64
+	url := fmt.Sprintf("http://%s:%d/api/%s/%s/_stream_load", c.FEHost, c.FEPort, database, table)
65
+
66
+	req, err := http.NewRequest("PUT", url, strings.NewReader(csvData))
67
+	if err != nil {
68
+		return fmt.Errorf("创建请求失败: %v", err)
69
+	}
70
+
71
+	req.SetBasicAuth(c.Username, c.Password)
72
+	req.Header.Set("Content-Type", "text/plain")
73
+	req.Header.Set("format", "csv")
74
+	req.Header.Set("column_separator", ",")
75
+
76
+	if skipHeader {
77
+		req.Header.Set("skip_header", "1")
78
+	}
79
+
80
+	resp, err := c.httpClient.Do(req)
81
+	if err != nil {
82
+		return fmt.Errorf("请求失败: %v", err)
83
+	}
84
+	defer resp.Body.Close()
85
+
86
+	body, _ := io.ReadAll(resp.Body)
87
+	if resp.StatusCode != 200 {
88
+		return fmt.Errorf("插入失败: %s", string(body))
89
+	}
90
+
91
+	// 解析Stream Load响应
92
+	var result struct {
93
+		Status  string `json:"Status"`
94
+		Message string `json:"Message"`
95
+	}
96
+	if err := json.Unmarshal(body, &result); err != nil {
97
+		return fmt.Errorf("解析响应失败: %v", err)
98
+	}
99
+
100
+	if result.Status != "Success" {
101
+		return fmt.Errorf("插入失败: %s", result.Message)
102
+	}
103
+
104
+	return nil
105
+}

+ 48
- 0
factory/http_factory.go Просмотреть файл

@@ -0,0 +1,48 @@
1
+package factory
2
+
3
+import (
4
+	"fmt"
5
+	"net/http"
6
+	"time"
7
+
8
+	"git.x2erp.com/qdy/go-base/config"
9
+)
10
+
11
+// HTTPFactory HTTP客户端工厂
12
+type HTTPFactory struct {
13
+	config config.IConfig
14
+	client *http.Client
15
+}
16
+
17
+// NewHTTPFactory 创建HTTP客户端工厂
18
+func NewHTTPFactory() (*HTTPFactory, error) {
19
+	cfg := config.GetConfig()
20
+
21
+	if err := config.GetInitError(); err != nil {
22
+		return nil, fmt.Errorf("failed to load config: %v", err)
23
+	}
24
+
25
+	client := &http.Client{
26
+		Timeout: 30 * time.Second,
27
+		Transport: &http.Transport{
28
+			MaxIdleConns:        100,
29
+			MaxIdleConnsPerHost: 10,
30
+			IdleConnTimeout:     90 * time.Second,
31
+		},
32
+	}
33
+
34
+	return &HTTPFactory{
35
+		config: cfg,
36
+		client: client,
37
+	}, nil
38
+}
39
+
40
+// CreateHTTPClient 创建HTTP客户端
41
+func (f *HTTPFactory) CreateHTTPClient() *http.Client {
42
+	return f.client
43
+}
44
+
45
+// GetConfig 获取配置信息
46
+func (f *HTTPFactory) GetConfig() config.IConfig {
47
+	return f.config
48
+}

+ 103
- 0
factory/redis_factory.go Просмотреть файл

@@ -0,0 +1,103 @@
1
+package factory
2
+
3
+import (
4
+	"context"
5
+	"fmt"
6
+	"time"
7
+
8
+	"git.x2erp.com/qdy/go-base/config"
9
+	"github.com/go-redis/redis/v8"
10
+)
11
+
12
+var ctx = context.Background()
13
+
14
+// RedisFactory Redis客户端工厂
15
+type RedisFactory struct {
16
+	config config.IConfig
17
+}
18
+
19
+// NewRedisFactory 创建Redis客户端工厂
20
+func NewRedisFactory() (*RedisFactory, error) {
21
+	cfg := config.GetConfig()
22
+
23
+	if err := config.GetInitError(); err != nil {
24
+		return nil, fmt.Errorf("failed to load config: %v", err)
25
+	}
26
+
27
+	if !cfg.IsRedisConfigured() {
28
+		return nil, fmt.Errorf("redis configuration is incomplete")
29
+	}
30
+
31
+	return &RedisFactory{config: cfg}, nil
32
+}
33
+
34
+// CreateRedisClient 创建Redis客户端
35
+func (f *RedisFactory) CreateRedisClient() *RedisClient {
36
+	redisConfig := f.config.GetRedis()
37
+
38
+	client := redis.NewClient(&redis.Options{
39
+		Addr:     fmt.Sprintf("%s:%d", redisConfig.Host, redisConfig.Port),
40
+		Password: redisConfig.Password,
41
+		DB:       redisConfig.DB,
42
+		PoolSize: redisConfig.PoolSize,
43
+	})
44
+
45
+	return &RedisClient{
46
+		client: client,
47
+	}
48
+}
49
+
50
+// RedisClient Redis客户端
51
+type RedisClient struct {
52
+	client *redis.Client
53
+}
54
+
55
+// Set 写入字符串值
56
+func (c *RedisClient) Set(key string, value interface{}, expiration time.Duration) error {
57
+	return c.client.Set(ctx, key, value, expiration).Err()
58
+}
59
+
60
+// Get 读取字符串值
61
+func (c *RedisClient) Get(key string) (string, error) {
62
+	return c.client.Get(ctx, key).Result()
63
+}
64
+
65
+// HSet 写入哈希字段
66
+func (c *RedisClient) HSet(key string, values ...interface{}) error {
67
+	return c.client.HSet(ctx, key, values...).Err()
68
+}
69
+
70
+// HGet 读取哈希字段
71
+func (c *RedisClient) HGet(key, field string) (string, error) {
72
+	return c.client.HGet(ctx, key, field).Result()
73
+}
74
+
75
+// HGetAll 读取整个哈希
76
+func (c *RedisClient) HGetAll(key string) (map[string]string, error) {
77
+	return c.client.HGetAll(ctx, key).Result()
78
+}
79
+
80
+// LPush 列表左推入
81
+func (c *RedisClient) LPush(key string, values ...interface{}) error {
82
+	return c.client.LPush(ctx, key, values...).Err()
83
+}
84
+
85
+// RPop 列表右弹出
86
+func (c *RedisClient) RPop(key string) (string, error) {
87
+	return c.client.RPop(ctx, key).Result()
88
+}
89
+
90
+// Del 删除键
91
+func (c *RedisClient) Del(keys ...string) error {
92
+	return c.client.Del(ctx, keys...).Err()
93
+}
94
+
95
+// Exists 检查键是否存在
96
+func (c *RedisClient) Exists(keys ...string) (int64, error) {
97
+	return c.client.Exists(ctx, keys...).Result()
98
+}
99
+
100
+// Close 关闭连接
101
+func (c *RedisClient) Close() error {
102
+	return c.client.Close()
103
+}

+ 1
- 1
go.mod Просмотреть файл

@@ -14,7 +14,7 @@ require gopkg.in/yaml.v2 v2.4.0 // indirect
14 14
 
15 15
 require (
16 16
 	filippo.io/edwards25519 v1.1.0 // indirect
17
-	git.x2erp.com/qdy/go-base v0.1.9
17
+	git.x2erp.com/qdy/go-base v0.1.10
18 18
 	github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
19 19
 	github.com/golang-sql/sqlexp v0.1.0 // indirect
20 20
 	github.com/google/uuid v1.6.0 // indirect

+ 8
- 0
go.sum Просмотреть файл

@@ -2,6 +2,8 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
2 2
 filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
3 3
 git.x2erp.com/qdy/go-base v0.1.9 h1:SuyYSt3Gp7aXiUQRCBNwhrusJ53wlCnagiTYs5eITlY=
4 4
 git.x2erp.com/qdy/go-base v0.1.9/go.mod h1:Q+YLwpCoU8CVSnzATLdz2LAzVMlz/CEGzo8DePf7cug=
5
+git.x2erp.com/qdy/go-base v0.1.10 h1:qHvRNSBoQHZfYrXUpZ42r925OO7aT95tIZK/qh6Cd60=
6
+git.x2erp.com/qdy/go-base v0.1.10/go.mod h1:Q+YLwpCoU8CVSnzATLdz2LAzVMlz/CEGzo8DePf7cug=
5 7
 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U=
6 8
 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM=
7 9
 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 h1:B+blDbyVIG3WaikNxPnhPiJ1MThR03b3vKGtER95TP4=
@@ -14,8 +16,14 @@ github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.1 h1:bFWuo
14 16
 github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.1/go.mod h1:Vih/3yc6yac2JzU4hzpaDupBJP0Flaia9rXXrU8xyww=
15 17
 github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJe7PpYPXT5A29ZkwJaPqcva7BVeemZOZs=
16 18
 github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
19
+github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
20
+github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
17 21
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
18 22
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
23
+github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
24
+github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
25
+github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
26
+github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
19 27
 github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
20 28
 github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
21 29
 github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=

Загрузка…
Отмена
Сохранить