Skip to content

Commit cfac91e

Browse files
committed
Init stable version
0 parents  commit cfac91e

26 files changed

+1556
-0
lines changed

.gitignore

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
### Go ###
2+
# Binaries for programs and plugins
3+
*.exe
4+
*.exe~
5+
*.dll
6+
*.so
7+
*.dylib
8+
9+
# Test binary, built with `go debug -c`
10+
*.test
11+
12+
# Output of the go coverage tool, specifically when used with LiteIDE
13+
*.out
14+
15+
# Dependency directories (remove the comment below to include it)
16+
# vendor/
17+
18+
### Go Patch ###
19+
/vendor/
20+
/Godeps/
21+
22+
### Goland ###
23+
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm, Rider and Goland
24+
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
25+
26+
# User-specific stuff
27+
.idea/**/workspace.xml
28+
.idea/**/tasks.xml
29+
.idea/**/usage.statistics.xml
30+
.idea/**/dictionaries
31+
.idea/**/shelf
32+
33+
# AWS User-specific
34+
.idea/**/aws.xml
35+
36+
# Generated files
37+
.idea/**/contentModel.xml
38+
39+
# Sensitive or high-churn files
40+
.idea/**/dataSources/
41+
.idea/**/dataSources.ids
42+
.idea/**/dataSources.local.xml
43+
.idea/**/sqlDataSources.xml
44+
.idea/**/dynamic.xml
45+
.idea/**/uiDesigner.xml
46+
.idea/**/dbnavigator.xml
47+
48+
# Gradle
49+
.idea/**/gradle.xml
50+
.idea/**/libraries
51+
52+
# Gradle and Maven with auto-import
53+
# When using Gradle or Maven with auto-import, you should exclude module files,
54+
# since they will be recreated, and may cause churn. Uncomment if using
55+
# auto-import.
56+
# .idea/artifacts
57+
# .idea/compiler.xml
58+
# .idea/jarRepositories.xml
59+
# .idea/modules.xml
60+
# .idea/*.iml
61+
# .idea/modules
62+
# *.iml
63+
# *.ipr
64+
65+
# CMake
66+
cmake-build-*/
67+
68+
# Mongo Explorer plugin
69+
.idea/**/mongoSettings.xml
70+
71+
# File-based project format
72+
*.iws
73+
74+
# IntelliJ
75+
out/
76+
77+
# mpeltonen/sbt-idea plugin
78+
.idea_modules/
79+
80+
# JIRA plugin
81+
atlassian-ide-plugin.xml
82+
83+
# Cursive Clojure plugin
84+
.idea/replstate.xml
85+
86+
# Crashlytics plugin (for Android Studio and IntelliJ)
87+
com_crashlytics_export_strings.xml
88+
crashlytics.properties
89+
crashlytics-build.properties
90+
fabric.properties
91+
92+
# Editor-based Rest Client
93+
.idea/httpRequests
94+
95+
# Ignores the whole .idea folder and all .iml files
96+
.idea/
97+
98+
# Android studio 3.1+ serialized cache file
99+
.idea/caches/build_file_checksums.ser
100+
101+
### Redis ###
102+
# Ignore redis binary dump (dump.rdb) files
103+
104+
*.rdb
105+
106+
# GRPC
107+
108+
*.pb.go

Dockerfile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
FROM golang:1.17
2+
3+
WORKDIR /go/src/app
4+
COPY . .
5+
6+
RUN go get -d -v ./...
7+
RUN go install -v ./...
8+
9+
CMD ["protoc -I . proto/*.proto --go_out=plugins=grpc:.","app"]

config/config.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package config
2+
3+
import (
4+
"gopkg.in/yaml.v2"
5+
"log"
6+
"os"
7+
)
8+
9+
type Config struct {
10+
Database struct {
11+
DbUri string `yaml:"uri"`
12+
DbName string `yaml:"name"`
13+
CollBoards string `yaml:"collection_boards"`
14+
CollThreads string `yaml:"collection_threads"`
15+
CollPosts string `yaml:"collection_posts"`
16+
} `yaml:"database"`
17+
Server struct {
18+
ServerHost string `yaml:"host"`
19+
ServerPort string `yaml:"port"`
20+
} `yaml:"server"`
21+
}
22+
23+
func NewConfig() *Config {
24+
25+
file, err := os.Open("config/config.yaml")
26+
if err != nil {
27+
log.Fatal(err)
28+
}
29+
defer func(file *os.File) {
30+
err := file.Close()
31+
if err != nil {
32+
log.Fatal(err)
33+
}
34+
}(file)
35+
36+
var cfg Config
37+
decoder := yaml.NewDecoder(file)
38+
err = decoder.Decode(&cfg)
39+
if err != nil {
40+
log.Fatal(err)
41+
}
42+
43+
return &cfg
44+
}

config/config.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
database:
2+
uri: mongodb://localhost:27017
3+
name: imageboard
4+
collection_boards: boards
5+
collection_threads: threads
6+
collection_posts: posts
7+
server:
8+
host: localhost
9+
port: 8080

data/db/database.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package db
2+
3+
import (
4+
"context"
5+
"go.mongodb.org/mongo-driver/mongo"
6+
"go.mongodb.org/mongo-driver/mongo/options"
7+
"grpcImageboard/config"
8+
"log"
9+
"time"
10+
)
11+
12+
type Database struct {
13+
Boards *mongo.Collection
14+
Threads *mongo.Collection
15+
Posts *mongo.Collection
16+
}
17+
18+
func NewDatabase(cfg config.Config, db *mongo.Database) Database {
19+
return Database{
20+
Boards: db.Collection(cfg.Database.CollBoards),
21+
Threads: db.Collection(cfg.Database.CollThreads),
22+
Posts: db.Collection(cfg.Database.CollPosts),
23+
}
24+
}
25+
26+
func Open(uri string) (*mongo.Client, context.Context, context.CancelFunc) {
27+
return connect(uri)
28+
}
29+
30+
func Close(client *mongo.Client, ctx context.Context, cancel context.CancelFunc) {
31+
disconnect(client, ctx, cancel)
32+
}
33+
34+
func connect(uri string) (*mongo.Client, context.Context, context.CancelFunc) {
35+
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
36+
client, err := mongo.Connect(ctx, options.Client().ApplyURI(uri).SetDirect(true).SetReplicaSet("rs0"))
37+
if err != nil {
38+
log.Println(err)
39+
} else {
40+
log.Println("Connected to DB")
41+
}
42+
return client, ctx, cancel
43+
}
44+
45+
func disconnect(client *mongo.Client, ctx context.Context, cancel context.CancelFunc) {
46+
47+
defer cancel()
48+
49+
defer func() {
50+
if err := client.Disconnect(ctx); err != nil {
51+
log.Println(err)
52+
} else {
53+
log.Println("Disconnected from DB")
54+
}
55+
}()
56+
}

data/repository/board_repository.go

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
package repository
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"go.mongodb.org/mongo-driver/bson"
7+
"go.mongodb.org/mongo-driver/bson/primitive"
8+
"go.mongodb.org/mongo-driver/mongo"
9+
"go.mongodb.org/mongo-driver/mongo/options"
10+
"grpcImageboard/config"
11+
"grpcImageboard/data/db"
12+
"grpcImageboard/domain"
13+
)
14+
15+
type boardRepository struct {
16+
cfg config.Config
17+
db db.Database
18+
}
19+
20+
func CreateBoardRepository(cfg config.Config, db db.Database) domain.BoardRepository {
21+
return &boardRepository{cfg, db}
22+
}
23+
24+
func (r *boardRepository) GetBoardsStream(ctx context.Context, changed func([]*domain.Board)) {
25+
stream, err := r.db.Boards.Watch(ctx, mongo.Pipeline{})
26+
if err != nil {
27+
fmt.Println(err)
28+
}
29+
defer func(stream *mongo.ChangeStream, ctx context.Context) {
30+
err := stream.Close(ctx)
31+
if err != nil {
32+
fmt.Println(err)
33+
}
34+
}(stream, ctx)
35+
for {
36+
select {
37+
case <-ctx.Done():
38+
err := stream.Close(ctx)
39+
if err != nil {
40+
fmt.Println(err)
41+
}
42+
return
43+
default:
44+
var data []*domain.Board
45+
ok := stream.Next(ctx)
46+
if !ok {
47+
err := stream.Err()
48+
if err != nil {
49+
println(err)
50+
return
51+
}
52+
}
53+
if ok {
54+
err := stream.Decode(data)
55+
if err != nil {
56+
println(err)
57+
return
58+
}
59+
changed(data)
60+
}
61+
}
62+
}
63+
64+
/*var result *bson.D
65+
for stream.Next(ctx) {
66+
if err := stream.Decode(&result); err != nil {
67+
fmt.Println(err)
68+
}
69+
fmt.Println(result)
70+
71+
filter, opts := &bson.M{}, options.Find()
72+
data, err := r.fetch(ctx, filter, opts)
73+
if err != nil {
74+
fmt.Println(err)
75+
}
76+
changed(data)
77+
}*/
78+
}
79+
80+
func (r *boardRepository) fetch(ctx context.Context, filter *bson.M, opts *options.FindOptions) ([]*domain.Board, error) {
81+
cursor, err := r.db.Boards.Find(ctx, filter, opts)
82+
if err != nil {
83+
return nil, err
84+
}
85+
defer func(cursor *mongo.Cursor, ctx context.Context) {
86+
err := cursor.Close(ctx)
87+
if err != nil {
88+
fmt.Println(err)
89+
return
90+
}
91+
}(cursor, ctx)
92+
data := make([]*domain.Board, 0)
93+
if err = cursor.All(ctx, &data); err != nil {
94+
return nil, err
95+
}
96+
return data, nil
97+
}
98+
99+
func (r *boardRepository) GetBoards(ctx context.Context, skip int64, limit int64) ([]*domain.Board, error) {
100+
filter, opts := &bson.M{}, options.Find().SetSkip(skip).SetLimit(limit)
101+
data, err := r.fetch(ctx, filter, opts)
102+
if err != nil {
103+
return nil, err
104+
}
105+
return data, nil
106+
}
107+
108+
func (r *boardRepository) GetBoardById(ctx context.Context, id string) (*domain.Board, error) {
109+
data := new(domain.Board)
110+
if err := r.db.Boards.FindOne(ctx, bson.M{"_id": bson.M{"$eq": id}}).Decode(&data); err != nil {
111+
return nil, err
112+
}
113+
return data, nil
114+
}
115+
116+
func (r *boardRepository) CreateBoard(ctx context.Context, board *domain.Board) (string, error) {
117+
board.Id = primitive.NewObjectID().Hex()
118+
_, err := r.db.Boards.InsertOne(ctx, board)
119+
if err != nil {
120+
return "", err
121+
}
122+
return board.Id, nil
123+
}
124+
125+
func (r *boardRepository) DeleteBoard(ctx context.Context, id string) (int64, error) {
126+
session, err := r.db.Boards.Database().Client().StartSession()
127+
if err != nil {
128+
return 0, err
129+
}
130+
var count int64 = 0
131+
if err = mongo.WithSession(ctx, session, func(sc mongo.SessionContext) error {
132+
result, err := r.db.Boards.DeleteOne(ctx, bson.M{"_id": id})
133+
if err != nil {
134+
return err
135+
}
136+
count = result.DeletedCount
137+
threadId, err := r.db.Threads.Find(ctx, bson.M{"board_id": id})
138+
if err != nil {
139+
return err
140+
}
141+
if _, err = r.db.Threads.DeleteMany(ctx, bson.M{"board_id": id}); err != nil {
142+
return err
143+
}
144+
if _, err = r.db.Posts.DeleteMany(ctx, bson.M{"thread_id": threadId}); err != nil {
145+
return err
146+
}
147+
return nil
148+
}); err != nil {
149+
return 0, err
150+
}
151+
return count, nil
152+
}

0 commit comments

Comments
 (0)