This commit is contained in:
2024-10-13 13:31:58 +04:00
commit aec8d7ed48
54 changed files with 2827 additions and 0 deletions

View File

@ -0,0 +1,38 @@
package postgres
import (
"fmt"
"time"
"github.com/aykhans/oh-my-chat/internal/adapter/config"
postgresDriver "gorm.io/driver/postgres"
"gorm.io/gorm"
)
func NewDB(config *config.PostgresConfig) (*gorm.DB, error) {
dsn := fmt.Sprintf(
"host=%s user=%s password=%s dbname=%s port=%s sslmode=%s TimeZone=%s",
config.Host,
config.User,
config.Password,
config.DBName,
config.Port,
"disable",
"UTC",
)
var db *gorm.DB
var err error
for range 3 {
db, err = gorm.Open(postgresDriver.Open(dsn), &gorm.Config{})
if err == nil {
break
}
time.Sleep(3 * time.Second)
}
if err != nil {
return nil, err
}
return db, nil
}

View File

@ -0,0 +1 @@
DROP TABLE IF EXISTS "public"."users";

View File

@ -0,0 +1,11 @@
CREATE TABLE "public"."users" (
"id" uuid NOT NULL DEFAULT gen_random_uuid(),
"username" character varying(50) NOT NULL,
"email" text NOT NULL,
"password" character varying(72) NOT NULL,
"created_at" timestamptz NOT NULL DEFAULT now(),
"updated_at" timestamptz NOT NULL DEFAULT now(),
PRIMARY KEY ("id"),
CONSTRAINT "uni_users_email" UNIQUE ("email"),
CONSTRAINT "uni_users_username" UNIQUE ("username")
);

View File

@ -0,0 +1,24 @@
package models
import (
"time"
"github.com/google/uuid"
)
const (
UserTableName = "users"
)
type User struct {
ID uuid.UUID `gorm:"primarykey;unique;type:uuid;default:gen_random_uuid()"`
Username string `gorm:"unique;not null;size:50"`
Email string `gorm:"unique;not null"`
Password string `gorm:"not null;size:72"`
CreatedAt time.Time
UpdatedAt time.Time
}
func (u User) TableName() string {
return UserTableName
}

View File

@ -0,0 +1,109 @@
package repository
import (
"context"
"errors"
"github.com/aykhans/oh-my-chat/internal/adapter/storages/postgres/models"
"github.com/aykhans/oh-my-chat/internal/core/domain"
"gorm.io/gorm"
)
type UserRepository struct {
db *gorm.DB
}
func NewUserRepository(db *gorm.DB) *UserRepository {
return &UserRepository{db}
}
func (userRepository *UserRepository) CreateUser(
ctx context.Context,
user *domain.User,
) (*domain.User, error) {
userModel := &models.User{
Username: user.Username,
Email: user.Email,
Password: user.Password,
}
tx := userRepository.db.Create(userModel)
if tx.Error != nil {
return nil, tx.Error
}
user.ID = userModel.ID
user.Username = userModel.Username
user.Email = userModel.Email
user.Password = userModel.Password
return user, nil
}
func (userRepository *UserRepository) IsUsernameExists(
ctx context.Context,
username string,
) (bool, error) {
var count int64
tx := userRepository.db.
Table(models.UserTableName).
Where("username = ?", username).
Count(&count)
if tx.Error != nil {
return false, tx.Error
}
return count > 0, nil
}
func (userRepository *UserRepository) IsEmailExists(
ctx context.Context,
email string,
) (bool, error) {
var count int64
tx := userRepository.db.
Table(models.UserTableName).
Where("email = ?", email).
Count(&count)
if tx.Error != nil {
return false, tx.Error
}
return count > 0, nil
}
func (userRepository *UserRepository) GetUserByEmail(
ctx context.Context,
email string,
) (*domain.User, error) {
user := &domain.User{}
tx := userRepository.db.
Table(models.UserTableName).
Where("email = ?", email).
First(user)
if tx.Error != nil {
if errors.Is(tx.Error, gorm.ErrRecordNotFound) {
return nil, domain.ErrDataNotFound
}
return nil, tx.Error
}
return user, nil
}
func (userRepository *UserRepository) GetUserByUsername(
ctx context.Context,
username string,
) (*domain.User, error) {
user := &domain.User{}
tx := userRepository.db.
Table(models.UserTableName).
Where("username = ?", username).
First(user)
if tx.Error != nil {
if errors.Is(tx.Error, gorm.ErrRecordNotFound) {
return nil, domain.ErrDataNotFound
}
return nil, tx.Error
}
return user, nil
}

View File

@ -0,0 +1,33 @@
package scylla
import (
"time"
"github.com/aykhans/oh-my-chat/internal/adapter/config"
"github.com/gocql/gocql"
)
func NewDB(config *config.ScyllaConfig) (*gocql.Session, error) {
cluster := gocql.NewCluster(config.Hosts...)
cluster.Keyspace = config.Keyspace
cluster.Consistency = gocql.LocalQuorum
cluster.Authenticator = gocql.PasswordAuthenticator{
Username: config.User,
Password: config.Password,
}
cluster.PoolConfig.HostSelectionPolicy = gocql.TokenAwareHostPolicy(
gocql.DCAwareRoundRobinPolicy(config.DataCenter),
)
var session *gocql.Session
var err error
for range 20 {
session, err = cluster.CreateSession()
if err == nil {
return session, nil
}
time.Sleep(3 * time.Second)
}
return nil, err
}

View File

@ -0,0 +1 @@
DROP TABLE IF EXISTS messages;

View File

@ -0,0 +1,8 @@
CREATE TABLE IF NOT EXISTS messages (
chat_id UUID, -- Partition key
user_id UUID,
content text, -- Clustering column
type text, -- Clustering column
created_at timestamp, -- Clustering column
PRIMARY KEY (chat_id, created_at, content, type)
) WITH CLUSTERING ORDER BY (created_at DESC);

View File

@ -0,0 +1 @@
DROP TABLE IF EXISTS user_chats;

View File

@ -0,0 +1,7 @@
CREATE TABLE IF NOT EXISTS user_chats (
user_id UUID, -- Partition key
chat_id UUID, -- Clustering column
blocked boolean,
created_at timestamp,
PRIMARY KEY (user_id, created_at, chat_id, blocked)
);

View File

@ -0,0 +1,23 @@
package repository
import (
"context"
"github.com/aykhans/oh-my-chat/internal/core/domain"
"github.com/gocql/gocql"
)
type MessageRepository struct {
db *gocql.Session
}
func NewMessageRepository(db *gocql.Session) *MessageRepository {
return &MessageRepository{db}
}
func (messageRepository *MessageRepository) CreateMessage(
ctx context.Context,
message *domain.Message,
) (*domain.Message, error) {
return nil, nil
}