Compare commits

...

2 Commits

Author SHA1 Message Date
daniel.w 350bbf086c add social_network repo 2024-09-03 09:17:50 +08:00
daniel.w 5599f88787 add user to nerwork 2024-09-02 21:43:03 +08:00
18 changed files with 323 additions and 15 deletions

View File

@ -20,3 +20,12 @@ TimelineSetting:
RedisCluster:
Host: 127.0.0.1:7001
Type: cluster
Neo4J:
URI: bolt://localhost:7687
Username: neo4j
Password: yyyytttt
MaxConnectionPoolSize: 20
MaxConnectionLifetime: 200s
ConnectionTimeout : 200s
LogLevel : debug

View File

@ -0,0 +1,5 @@
// 企業版才能用,社群版只能用預設的
CREATE DATABASE relation;
// 創建 User 節點 UID 是唯一鍵
CREATE CONSTRAINT FOR (u:User) REQUIRE u.UID IS UNIQUE

View File

@ -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
View File

@ -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

View File

@ -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
}
}

View File

@ -0,0 +1,7 @@
package repository
import "context"
type SocialNetworkRepository interface {
CreateUserNode(ctx context.Context, uid string) error
}

View File

@ -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
}

View File

@ -0,0 +1,53 @@
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,
serviceConf: Config{
URI: conf.URI,
Username: conf.Username,
Password: conf.Password,
LogLevel: conf.LogLevel,
},
}
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)
}
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
}

View File

@ -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
}
}
}

View File

@ -0,0 +1,37 @@
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 {
fmt.Println("gg88g88g8", err)
return nil, err
}
fmt.Println(err)
return &tweeting.OKResp{}, nil
}

View File

@ -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"
"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 {
session, err := s.neo4jClient.Conn()
if err != nil {
return err
}
defer session.Close(ctx)
params := map[string]interface{}{
"uid": uid,
}
_, err = session.NewSession(ctx, neo4j.SessionConfig{
AccessMode: neo4j.AccessModeWrite,
}).Run(ctx, "CREATE (n:User {uid: $uid}) RETURN n", params)
if err != nil {
return err
}
// // 處理結果
// if run.Next(ctx) {
// node := run.Record().AsMap()
// fmt.Printf("Created Node: %v\n", node)
// }
return nil
}

View File

@ -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,

View File

@ -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"
)

View File

@ -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"
)

View File

@ -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)
}

View File

@ -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"
)

View File

@ -3,9 +3,9 @@ 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"
"github.com/zeromicro/go-zero/core/stores/redis"
vi "code.30cm.net/digimon/library-go/validator"
@ -14,11 +14,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 +26,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,
}),
}
}

View File

@ -6,7 +6,10 @@ import (
"app-cloudep-tweeting-service/gen_result/pb/tweeting"
"app-cloudep-tweeting-service/internal/config"
commentserviceServer "app-cloudep-tweeting-service/internal/server/commentservice"
postserviceServer "app-cloudep-tweeting-service/internal/server/postservice"
socialnetworkserviceServer "app-cloudep-tweeting-service/internal/server/socialnetworkservice"
timelineserviceServer "app-cloudep-tweeting-service/internal/server/timelineservice"
"app-cloudep-tweeting-service/internal/svc"
"github.com/zeromicro/go-zero/core/conf"
@ -18,8 +21,6 @@ import (
var configFile = flag.String("f", "etc/tweeting.yaml", "the config file")
// TODO 要把每一個錯誤代碼修改的更詳細,目前都資料庫錯誤
func main() {
flag.Parse()
@ -29,6 +30,9 @@ func main() {
s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {
tweeting.RegisterPostServiceServer(grpcServer, postserviceServer.NewPostServiceServer(ctx))
tweeting.RegisterCommentServiceServer(grpcServer, commentserviceServer.NewCommentServiceServer(ctx))
tweeting.RegisterTimelineServiceServer(grpcServer, timelineserviceServer.NewTimelineServiceServer(ctx))
tweeting.RegisterSocialNetworkServiceServer(grpcServer, socialnetworkserviceServer.NewSocialNetworkServiceServer(ctx))
if c.Mode == service.DevMode || c.Mode == service.TestMode {
reflection.Register(grpcServer)