add user to nerwork
This commit is contained in:
parent
f135327805
commit
5599f88787
|
@ -20,3 +20,12 @@ TimelineSetting:
|
|||
RedisCluster:
|
||||
Host: 127.0.0.1:7001
|
||||
Type: cluster
|
||||
|
||||
Neo4J:
|
||||
URI: neo4j://localhost:7687
|
||||
Username: neo4j
|
||||
Password: yyyytttt
|
||||
MaxConnectionPoolSize: 20
|
||||
MaxConnectionLifetime: 200s
|
||||
ConnectionTimeout : 200s
|
||||
LogLevel : debug
|
|
@ -0,0 +1,5 @@
|
|||
// 企業版才能用,社群版只能用預設的
|
||||
CREATE DATABASE relation;
|
||||
|
||||
// 創建 User 節點 UID 是唯一鍵
|
||||
CREATE CONSTRAINT FOR (u:User) REQUIRE u.UID IS UNIQUE
|
|
@ -243,3 +243,15 @@ service TimelineService
|
|||
// ClearNoMoreDataFlag 清除時間線的 "NoMoreData" 標誌。
|
||||
rpc ClearNoMoreDataFlag(DoNoMoreDataReq) returns (OKResp);
|
||||
}
|
||||
|
||||
// ========== Social Network (關係網路) ==========
|
||||
|
||||
message AddUserToNetworkReq
|
||||
{
|
||||
string uid = 1;
|
||||
}
|
||||
|
||||
service SocialNetworkService
|
||||
{
|
||||
rpc AddUserToNetwork(AddUserToNetworkReq) returns (OKResp);
|
||||
}
|
1
go.mod
1
go.mod
|
@ -6,6 +6,7 @@ require (
|
|||
code.30cm.net/digimon/library-go/errs v1.2.4
|
||||
code.30cm.net/digimon/library-go/validator v1.0.0
|
||||
github.com/alicebob/miniredis/v2 v2.33.0
|
||||
github.com/neo4j/neo4j-go-driver/v5 v5.24.0
|
||||
github.com/stretchr/testify v1.9.0
|
||||
github.com/zeromicro/go-zero v1.7.0
|
||||
go.mongodb.org/mongo-driver v1.16.0
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/stores/redis"
|
||||
"github.com/zeromicro/go-zero/zrpc"
|
||||
)
|
||||
|
@ -24,4 +26,15 @@ type Config struct {
|
|||
|
||||
// Redis Cluster
|
||||
RedisCluster redis.RedisConf
|
||||
|
||||
// 圖形話資料庫
|
||||
Neo4J struct {
|
||||
URI string
|
||||
Username string
|
||||
Password string
|
||||
MaxConnectionPoolSize int
|
||||
MaxConnectionLifetime time.Duration
|
||||
ConnectionTimeout time.Duration
|
||||
LogLevel string
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
package repository
|
||||
|
||||
import "context"
|
||||
|
||||
type SocialNetworkRepository interface {
|
||||
CreateUserNode(ctx context.Context, uid string) error
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package neo4j
|
||||
|
||||
import "time"
|
||||
|
||||
// Config holds the configuration for Neo4j connection.
|
||||
type Config struct {
|
||||
URI string
|
||||
Username string
|
||||
Password string
|
||||
MaxConnectionPoolSize int
|
||||
MaxConnectionLifetime time.Duration
|
||||
ConnectionTimeout time.Duration
|
||||
LogLevel string
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package neo4j
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
|
||||
n4Cfg "github.com/neo4j/neo4j-go-driver/v5/neo4j/config"
|
||||
)
|
||||
|
||||
// NewNeo4J initializes a Neo4jInit using the provided Config and options.
|
||||
// If opts is not provided, it will initialize Neo4jInit with default configuration.
|
||||
func NewNeo4J(conf *Config, opts ...Option) *Client {
|
||||
driverConfig := &n4Cfg.Config{
|
||||
MaxConnectionLifetime: conf.MaxConnectionLifetime,
|
||||
MaxConnectionPoolSize: conf.MaxConnectionPoolSize,
|
||||
ConnectionAcquisitionTimeout: conf.ConnectionTimeout,
|
||||
}
|
||||
|
||||
neo4ji := &Client{
|
||||
neo4jConf: driverConfig,
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(neo4ji)
|
||||
}
|
||||
|
||||
return neo4ji
|
||||
}
|
||||
|
||||
// Conn initiates connection to the database and returns a Neo4j driver instance.
|
||||
func (c *Client) Conn() (neo4j.DriverWithContext, error) {
|
||||
auth := neo4j.BasicAuth(c.serviceConf.Username, c.serviceConf.Password, "")
|
||||
driver, err := neo4j.NewDriverWithContext(c.serviceConf.URI, auth, func(c *n4Cfg.Config) {})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("neo4j driver initialization error: %w", err)
|
||||
}
|
||||
defer func(driver neo4j.DriverWithContext, ctx context.Context) {
|
||||
err := driver.Close(ctx)
|
||||
if err != nil {
|
||||
// fmt
|
||||
|
||||
}
|
||||
}(driver, context.Background())
|
||||
|
||||
ctx := context.Background()
|
||||
// Verify the connection to Neo4j.
|
||||
err = driver.VerifyConnectivity(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("neo4j connectivity verification error: %w", err)
|
||||
}
|
||||
|
||||
return driver, nil
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
package neo4j
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
n4Cfg "github.com/neo4j/neo4j-go-driver/v5/neo4j/config"
|
||||
"github.com/neo4j/neo4j-go-driver/v5/neo4j/log"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultMaxConnectionLifetime = 5 * time.Minute
|
||||
defaultMaxConnectionPoolSize = 25
|
||||
defaultConnectionTimeout = 5 * time.Second
|
||||
)
|
||||
|
||||
// Option configures Neo4jInit behaviour.
|
||||
type Option func(*Client)
|
||||
|
||||
type Client struct {
|
||||
neo4jConf *n4Cfg.Config
|
||||
serviceConf Config
|
||||
}
|
||||
|
||||
// WithLogLevel sets the log level for the Neo4j driver.
|
||||
func WithLogLevel(level string) Option {
|
||||
return func(neo4ji *Client) {
|
||||
var logger log.Logger
|
||||
|
||||
switch strings.ToLower(level) {
|
||||
case "panic", "fatal", "error":
|
||||
logger = log.ToConsole(log.ERROR)
|
||||
case "warn", "warning":
|
||||
logger = log.ToConsole(log.WARNING)
|
||||
case "info", "debug", "trace":
|
||||
logger = log.ToConsole(log.INFO)
|
||||
default:
|
||||
logger = log.ToConsole(log.ERROR)
|
||||
}
|
||||
|
||||
neo4ji.neo4jConf.Log = logger
|
||||
}
|
||||
}
|
||||
|
||||
// WithPerformance configures the Neo4j driver for performance by setting connection pool size and lifetime.
|
||||
func WithPerformance() Option {
|
||||
return func(neo4ji *Client) {
|
||||
if neo4ji.serviceConf.MaxConnectionPoolSize > 0 {
|
||||
neo4ji.neo4jConf.MaxConnectionPoolSize = neo4ji.serviceConf.MaxConnectionPoolSize
|
||||
} else {
|
||||
neo4ji.neo4jConf.MaxConnectionPoolSize = defaultMaxConnectionPoolSize
|
||||
}
|
||||
|
||||
if neo4ji.serviceConf.MaxConnectionLifetime > 0 {
|
||||
neo4ji.neo4jConf.MaxConnectionLifetime = neo4ji.serviceConf.MaxConnectionLifetime
|
||||
} else {
|
||||
neo4ji.neo4jConf.MaxConnectionLifetime = defaultMaxConnectionLifetime
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package socialnetworkservicelogic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"app-cloudep-tweeting-service/gen_result/pb/tweeting"
|
||||
"app-cloudep-tweeting-service/internal/svc"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type AddUserToNetworkLogic struct {
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
logx.Logger
|
||||
}
|
||||
|
||||
func NewAddUserToNetworkLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AddUserToNetworkLogic {
|
||||
return &AddUserToNetworkLogic{
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
Logger: logx.WithContext(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
func (l *AddUserToNetworkLogic) AddUserToNetwork(in *tweeting.AddUserToNetworkReq) (*tweeting.OKResp, error) {
|
||||
// todo: add your logic here and delete this line
|
||||
err := l.svcCtx.SocialNetworkRepository.CreateUserNode(l.ctx, in.GetUid())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Println(err)
|
||||
|
||||
return &tweeting.OKResp{}, nil
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package repository
|
||||
|
||||
import (
|
||||
"app-cloudep-tweeting-service/internal/config"
|
||||
"app-cloudep-tweeting-service/internal/domain/repository"
|
||||
client4J "app-cloudep-tweeting-service/internal/lib/neo4j"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
ers "code.30cm.net/digimon/library-go/errs"
|
||||
n4 "github.com/neo4j/neo4j-go-driver/v5/neo4j"
|
||||
)
|
||||
|
||||
type SocialNetworkParam struct {
|
||||
Config config.Config
|
||||
Neo4jClient *client4J.Client
|
||||
}
|
||||
|
||||
type SocialNetworkRepository struct {
|
||||
cfg config.Config
|
||||
neo4jClient *client4J.Client
|
||||
}
|
||||
|
||||
func MustSocialNetworkRepository(param SocialNetworkParam) repository.SocialNetworkRepository {
|
||||
return &SocialNetworkRepository{
|
||||
cfg: param.Config,
|
||||
neo4jClient: param.Neo4jClient,
|
||||
}
|
||||
}
|
||||
|
||||
func (s SocialNetworkRepository) CreateUserNode(ctx context.Context, uid string) error {
|
||||
// 執行 Cypher
|
||||
conn, err := s.neo4jClient.Conn()
|
||||
if err != nil {
|
||||
return ers.DBError("failed to connect to node4j", err.Error())
|
||||
}
|
||||
|
||||
insert := map[string]any{
|
||||
"uid": uid,
|
||||
}
|
||||
|
||||
result, err := conn.NewSession(ctx, n4.SessionConfig{
|
||||
AccessMode: n4.AccessModeWrite,
|
||||
}).Run(ctx, "CREATE (n:Person {name: $name}) RETURN n", insert)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println(result.Keys())
|
||||
|
||||
return nil
|
||||
|
||||
}
|
|
@ -24,7 +24,7 @@ type TimelineRepository struct {
|
|||
redis redis.Redis
|
||||
}
|
||||
|
||||
func MustGenerateUseCase(param TimelineRepositoryParam) repository.TimelineRepository {
|
||||
func MustGenerateRepository(param TimelineRepositoryParam) repository.TimelineRepository {
|
||||
return &TimelineRepository{
|
||||
cfg: param.Config,
|
||||
redis: param.Redis,
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"context"
|
||||
|
||||
"app-cloudep-tweeting-service/gen_result/pb/tweeting"
|
||||
commentservicelogic "app-cloudep-tweeting-service/internal/logic/commentservice"
|
||||
"app-cloudep-tweeting-service/internal/logic/commentservice"
|
||||
"app-cloudep-tweeting-service/internal/svc"
|
||||
)
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"context"
|
||||
|
||||
"app-cloudep-tweeting-service/gen_result/pb/tweeting"
|
||||
postservicelogic "app-cloudep-tweeting-service/internal/logic/postservice"
|
||||
"app-cloudep-tweeting-service/internal/logic/postservice"
|
||||
"app-cloudep-tweeting-service/internal/svc"
|
||||
)
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
// Code generated by goctl. DO NOT EDIT.
|
||||
// Source: tweeting.proto
|
||||
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"app-cloudep-tweeting-service/gen_result/pb/tweeting"
|
||||
"app-cloudep-tweeting-service/internal/logic/socialnetworkservice"
|
||||
"app-cloudep-tweeting-service/internal/svc"
|
||||
)
|
||||
|
||||
type SocialNetworkServiceServer struct {
|
||||
svcCtx *svc.ServiceContext
|
||||
tweeting.UnimplementedSocialNetworkServiceServer
|
||||
}
|
||||
|
||||
func NewSocialNetworkServiceServer(svcCtx *svc.ServiceContext) *SocialNetworkServiceServer {
|
||||
return &SocialNetworkServiceServer{
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SocialNetworkServiceServer) AddUserToNetwork(ctx context.Context, in *tweeting.AddUserToNetworkReq) (*tweeting.OKResp, error) {
|
||||
l := socialnetworkservicelogic.NewAddUserToNetworkLogic(ctx, s.svcCtx)
|
||||
return l.AddUserToNetwork(in)
|
||||
}
|
|
@ -7,7 +7,7 @@ import (
|
|||
"context"
|
||||
|
||||
"app-cloudep-tweeting-service/gen_result/pb/tweeting"
|
||||
timelineservicelogic "app-cloudep-tweeting-service/internal/logic/timelineservice"
|
||||
"app-cloudep-tweeting-service/internal/logic/timelineservice"
|
||||
"app-cloudep-tweeting-service/internal/svc"
|
||||
)
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package svc
|
|||
import (
|
||||
"app-cloudep-tweeting-service/internal/config"
|
||||
domainRepo "app-cloudep-tweeting-service/internal/domain/repository"
|
||||
"app-cloudep-tweeting-service/internal/lib/neo4j"
|
||||
model "app-cloudep-tweeting-service/internal/model/mongo"
|
||||
"app-cloudep-tweeting-service/internal/repository"
|
||||
|
||||
|
@ -14,11 +15,10 @@ import (
|
|||
type ServiceContext struct {
|
||||
Config config.Config
|
||||
Validate vi.Validate
|
||||
|
||||
PostModel model.PostModel
|
||||
CommentModel model.CommentModel
|
||||
|
||||
TimelineRepo domainRepo.TimelineRepository
|
||||
SocialNetworkRepository domainRepo.SocialNetworkRepository
|
||||
}
|
||||
|
||||
func NewServiceContext(c config.Config) *ServiceContext {
|
||||
|
@ -27,14 +27,27 @@ func NewServiceContext(c config.Config) *ServiceContext {
|
|||
panic(err)
|
||||
}
|
||||
|
||||
neoClient := neo4j.NewNeo4J(&neo4j.Config{
|
||||
URI: c.Neo4J.URI,
|
||||
Username: c.Neo4J.Username,
|
||||
Password: c.Neo4J.Password,
|
||||
MaxConnectionPoolSize: c.Neo4J.MaxConnectionPoolSize,
|
||||
MaxConnectionLifetime: c.Neo4J.MaxConnectionLifetime,
|
||||
ConnectionTimeout: c.Neo4J.ConnectionTimeout,
|
||||
}, neo4j.WithPerformance(), neo4j.WithLogLevel(c.Neo4J.LogLevel))
|
||||
|
||||
return &ServiceContext{
|
||||
Config: c,
|
||||
Validate: vi.MustValidator(),
|
||||
PostModel: MustPostModel(c),
|
||||
CommentModel: MustCommentModel(c),
|
||||
TimelineRepo: repository.MustGenerateUseCase(repository.TimelineRepositoryParam{
|
||||
TimelineRepo: repository.MustGenerateRepository(repository.TimelineRepositoryParam{
|
||||
Config: c,
|
||||
Redis: *newRedis,
|
||||
}),
|
||||
SocialNetworkRepository: repository.MustSocialNetworkRepository(repository.SocialNetworkParam{
|
||||
Config: c,
|
||||
Neo4jClient: neoClient,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue