Skip to content

Commit

Permalink
Merge pull request #1 from satanaroom/task2
Browse files Browse the repository at this point in the history
Task2
  • Loading branch information
satanaroom committed May 11, 2023
2 parents 68a86d1 + ad86cbc commit bede6e0
Show file tree
Hide file tree
Showing 16 changed files with 737 additions and 0 deletions.
43 changes: 43 additions & 0 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Go

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:

build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.19

- name: Build
run: go build -v ./...

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

linter:
strategy:
matrix:
go-version: [1.19.x]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}
- name: Checkout code
uses: actions/checkout@v2
- name: Run linters
uses: golangci/golangci-lint-action@v2
with:
version: latest
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,7 @@

# Go workspace file
go.work

/bin
/.idea
.env
21 changes: 21 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
LOCAL_BIN:=$(CURDIR)/bin

install-go-deps:
GOBIN=$(LOCAL_BIN) go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28.1
GOBIN=$(LOCAL_BIN) go install -mod=mod google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2


.PHONY: lint
lint:
golangci-lint run

.PHONY: cover
cover:
go test -short -count=1 -race -coverprofile=coverage.out ./...
go tool cover -html=coverage.out
rm coverage.out

.PHONY: gen
gen:
mockgen -source=internal/repository/chat_server/repository.go \
-destination=internal/repository/mocks/mock_repository.go
25 changes: 25 additions & 0 deletions cmd/server/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package main

import (
"context"

"github.com/satanaroom/auth/pkg/logger"
"github.com/satanaroom/chat_server/internal/app"
)

func main() {
ctx := context.Background()

chatApp, err := app.NewApp(ctx)
if err != nil {
logger.Fatalf("failed to initialize app: %s", err.Error())
}

logger.Info("service starting up")

if err = chatApp.Run(); err != nil {
logger.Fatalf("failed to run app: %s", err.Error())
}

logger.Info("service shutting down")
}
31 changes: 31 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
module github.com/satanaroom/chat_server

go 1.20

require (
github.com/georgysavva/scany v1.2.1
github.com/jackc/pgconn v1.14.0
github.com/jackc/pgx/v4 v4.18.1
github.com/joho/godotenv v1.5.1
github.com/satanaroom/auth v0.0.0-20230504071525-1f1c0514db48
)

require (
github.com/golang/protobuf v1.5.2 // indirect
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
github.com/jackc/pgio v1.0.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgproto3/v2 v2.3.2 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgtype v1.14.0 // indirect
github.com/jackc/puddle v1.3.0 // indirect
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
github.com/sirupsen/logrus v1.4.2 // indirect
golang.org/x/crypto v0.8.0 // indirect
golang.org/x/net v0.9.0 // indirect
golang.org/x/sys v0.7.0 // indirect
golang.org/x/text v0.9.0 // indirect
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
google.golang.org/grpc v1.54.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect
)
270 changes: 270 additions & 0 deletions go.sum

Large diffs are not rendered by default.

55 changes: 55 additions & 0 deletions internal/app/app.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package app

import (
"context"
"fmt"

"github.com/satanaroom/chat_server/internal/closer"
"github.com/satanaroom/chat_server/internal/config"
)

type App struct {
serviceProvider *serviceProvider
}

func NewApp(ctx context.Context) (*App, error) {
a := &App{}

if err := a.initDeps(ctx); err != nil {
return nil, fmt.Errorf("init deps: %w", err)
}

return a, nil
}

func (a *App) Run() error {
defer func() {
closer.CloseAll()
closer.Wait()
}()

// TODO: run some server

return nil
}

func (a *App) initDeps(ctx context.Context) error {
inits := []func(context.Context) error{
config.Init,

a.initServiceProvider,
}

for _, f := range inits {
if err := f(ctx); err != nil {
return fmt.Errorf("init: %w", err)
}
}

return nil
}

func (a *App) initServiceProvider(_ context.Context) error {
a.serviceProvider = newServiceProvider()
return nil
}
48 changes: 48 additions & 0 deletions internal/app/service_provider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package app

import (
"context"

authV1 "github.com/satanaroom/auth/pkg/auth_v1"
"github.com/satanaroom/auth/pkg/logger"

authClient "github.com/satanaroom/chat_server/internal/clients/grpc/auth"
"github.com/satanaroom/chat_server/internal/closer"
"github.com/satanaroom/chat_server/internal/config"
chatService "github.com/satanaroom/chat_server/internal/service/chat"
"google.golang.org/grpc"
)

type serviceProvider struct {
authConfig config.AuthClientConfig

authClient authClient.Client
chatService chatService.Service
}

func newServiceProvider() *serviceProvider {
return &serviceProvider{}
}

func (s *serviceProvider) ChatService(ctx context.Context) chatService.Service {
if s.chatService == nil {
s.chatService = chatService.NewService(s.AuthClient(ctx))
}

return s.chatService
}

func (s *serviceProvider) AuthClient(_ context.Context) authClient.Client {
if s.authClient == nil {
conn, err := grpc.Dial(s.authConfig.Port(), grpc.WithDefaultCallOptions())
if err != nil {
logger.Fatalf("failed to connect %s: %s", s.authConfig.Port(), err.Error())
}
closer.Add(conn.Close)

client := authV1.NewAuthV1Client(conn)
s.authClient = authClient.NewClient(client)
}

return s.authClient
}
35 changes: 35 additions & 0 deletions internal/clients/grpc/auth/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package auth

import (
"context"
"fmt"

authV1 "github.com/satanaroom/auth/pkg/auth_v1"
"github.com/satanaroom/chat_server/internal/converter/client/auth"
"github.com/satanaroom/chat_server/internal/model"
)

var _ Client = (*client)(nil)

type Client interface {
Create(ctx context.Context, info *model.UserInfo) (int64, error)
}

type client struct {
authClient authV1.AuthV1Client
}

func NewClient(cl authV1.AuthV1Client) *client {
return &client{
authClient: cl,
}
}

func (c *client) Create(ctx context.Context, info *model.UserInfo) (int64, error) {
resp, err := c.authClient.Create(ctx, auth.ToCreateRequest(info))
if err != nil {
return 0, fmt.Errorf("authClient.Create: %w", err)
}

return auth.FromCreateResponse(resp), nil
}
87 changes: 87 additions & 0 deletions internal/closer/closer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package closer

import (
"context"
"log"
"os"
"os/signal"
"sync"
)

var globalCloser = New()

// Add adds `func() error` callback to the globalCloser
func Add(f ...func() error) {
globalCloser.Add(f...)
}

// Wait ...
func Wait() {
globalCloser.Wait()
}

// CloseAll ...
func CloseAll() {
globalCloser.CloseAll()
}

// Closer ...
type Closer struct {
mu sync.Mutex
once sync.Once
done chan struct{}
funcs []func() error
}

// New returns new Closer, if []os.Signal is specified Closer will automatically call CloseAll when one of signals is received from OS
func New(sig ...os.Signal) *Closer {
c := &Closer{done: make(chan struct{})}
if len(sig) > 0 {
go func() {
ch := make(chan os.Signal, 1)
signal.Notify(ch, sig...)
<-ch
signal.Stop(ch)
c.CloseAll()
}()
}
return c
}

// Add func to closer
func (c *Closer) Add(f ...func() error) {
c.mu.Lock()
c.funcs = append(c.funcs, f...)
c.mu.Unlock()
}

// Wait blocks until all closer functions are done
func (c *Closer) Wait() {
<-c.done
}

// CloseAll calls all closer functions
func (c *Closer) CloseAll() {
c.once.Do(func() {
defer close(c.done)

c.mu.Lock()
funcs := c.funcs
c.funcs = nil
c.mu.Unlock()

// call all Closer funcs async
errs := make(chan error, len(funcs))
for _, f := range funcs {
go func(f func() error) {
errs <- f()
}(f)
}

for i := 0; i < cap(errs); i++ {
if err := <-errs; err != nil {
log.Println(context.Background(), "error returned from Closer: %v", err)
}
}
})
}
34 changes: 34 additions & 0 deletions internal/config/auth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package config

import (
"os"

"github.com/satanaroom/chat_server/internal/errs"
)

var _ AuthClientConfig = (*authClientConfig)(nil)

const authPortEnvName = "AUTH_PORT"

type AuthClientConfig interface {
Port() string
}

type authClientConfig struct {
port string
}

func NewAuthClientConfig() (*authClientConfig, error) {
port := os.Getenv(authPortEnvName)
if port == "" {
return nil, errs.ErrAuthClientPortNotFound
}

return &authClientConfig{
port: port,
}, nil
}

func (c *authClientConfig) Port() string {
return c.port
}
Loading

0 comments on commit bede6e0

Please sign in to comment.