Skip to content

TonyPath/user-mng-grpc-service

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GRPC User management service

go.mod Go version

Infra

DB/Storage

The service uses PostgreSQL to store its state

Streaming

The service uses Kafka to produce events for other services

Kafka Topic Message Type
UserCreated UserCreated
UserUpdated UserUpdated

Project structure

/proto-schemas

Message and RPC definitions. To generate the go specific source code type:

make gen-proto

/proto

Output directory of gRPC and messages specific go source code.

/infra

Contains files to dockerize the application

/transport/grpc

GRPC Server that serves the user management API

/transport/http

HTTP Infra server exposes health check endpoints(readiness, liveness)

/stream

Kafka producer

/internal

Core application logic (config, services, repositories, models)

/dockertest

Utilities to used for integration tests with the help of docker api

Class Diagram

classDiagram
class userStorage {
    <<interface>>
    InsertUser(user models.User) (uuid.UUID, error)
    UpdateUser(userID uuid.UUID, user models.User) error
    DeleteUser(userID uuid.UUID) error
    GetUsersByFilter(opts models.GetUsersOptions) ([]models.User, error)
    GetUserByID(userID uuid.UUID) (models.User, error)
    ExistsByID(userID uuid.UUID) (bool, error)
}
class Repository {
    db *sql.DB
}
userStorage <.. Repository : Satisfies


class eventPublisher {
    <<interface>>
    Publish(topic string, key string, pbMessage proto.Message) error
}
class EventPublisher {
    client sarama.Client
}
eventPublisher <.. EventPublisher : Satisfies

class UserService{
    repo userStorage
    eventPublisher eventPublisher
}
Repository <|-- UserService : Uses
EventPublisher <|-- UserService : Uses


class userService {
    <<interface>>
    CreateUser(nu models.NewUser) (uuid.UUID, error)
    UpdateUser(userID uuid.UUID, uu models.UpdateUser) error
	DeleteUser(userID uuid.UUID) error
	GetUsers(qu models.GetUsersOptions) ([]models.User, error)
}

userService <.. UserService : Satisfies

class GRPC {
    svc userService
}

UserService <|-- GRPC : Uses

proto_UnimplementedUserServer <.. GRPC : Satisfies

class proto_UnimplementedUserServer {
    <<interface>>
    CreateUser(*CreateUserRequest) (*CreateUserResponse, error)
	UpdateUser(*UpdateUserRequest) (*UpdateUserResponse, error)
	DeleteUser(*DeleteUserRequest) (*DeleteUserResponse, error)
	QueryUsers(*QueryUsersRequest) (*QueryUsersResponse, error)
}

Loading

How to start, use and stop


To start the service type

make serve

To view logs of the service type

make logs

Usage examples:

Create user
$ grpcurl -d '{"email":"user1@mail.com","first_name":"user1_name","last_name":"user1_lname","nickname":"user1_nkname","password":"secret","country":"GR"}' -plaintext localhost:50000 services.user.User/CreateUser
{
  "userId": "166f7137-8884-42ab-90b2-1c2d77fc1037"
}
Listing all users (default page size = 10)
$ grpcurl -d '{}' -plaintext localhost:50000 services.user.User/QueryUsers
{
  "users": [
    {
      "id": "166f7137-8884-42ab-90b2-1c2d77fc1037",
      "email": "user1@mail.com",
      "firstName": "user1_name",
      "lastName": "user1_lname",
      "nickname": "user1_nkname",
      "country": "GR",
      "password": "$2a$10$LpgLzRcXkxU45Wwqgd.d9evdJ0wAV63LCFeLm.J78k2d1FBbnPNXG",
      "createdAt": "2022-08-16T22:54:06.419671Z"
    },
    {
      "id": "b3ce8fed-d5e8-4583-8783-b95969b5bc0c",
      "email": "user2@mail.com",
      "firstName": "user2_name",
      "lastName": "user2_lname",
      "nickname": "user2_nkname",
      "country": "GR",
      "password": "$2a$10$wNV.oRXIaAjPCbZp01zrf.KBwCq98AZZ1lEAEq/0VMEaEMlUSHiN6",
      "createdAt": "2022-08-16T22:54:34.134916Z"
    },
    {
      "id": "5631dc46-54a4-4f00-a296-faa248a98e8d",
      "email": "user3@mail.com",
      "firstName": "user3_name",
      "lastName": "user3_lname",
      "nickname": "user3_nkname",
      "country": "UK",
      "password": "$2a$10$KaIyJrMd3.o.KCSIQSV2MOdeIney1ejjdAcspFyLT3ysJwAraV.D.",
      "createdAt": "2022-08-16T22:54:58.116917Z"
    }
  ]
}
Listing all users in UK
$ grpcurl -d '{"filter":{"country":"UK"}}' -plaintext localhost:50000 services.user.User/QueryUsers 
{
  "users": [
    {
      "id": "5631dc46-54a4-4f00-a296-faa248a98e8d",
      "email": "user3@mail.com",
      "firstName": "user3_name",
      "lastName": "user3_lname",
      "nickname": "user3_nkname",
      "country": "UK",
      "password": "$2a$10$KaIyJrMd3.o.KCSIQSV2MOdeIney1ejjdAcspFyLT3ysJwAraV.D.",
      "createdAt": "2022-08-16T22:54:58.116917Z"
    }
  ]
}
Listing users in GR (1st page)
$ grpcurl -d '{"page_size":1, "page_number":1 ,"filter":{"country":"GR"}}' -plaintext localhost:50000 services.user.User/QueryUsers
{
  "users": [
    {
      "id": "166f7137-8884-42ab-90b2-1c2d77fc1037",
      "email": "user1@mail.com",
      "firstName": "user1_name",
      "lastName": "user1_lname",
      "nickname": "user1_nkname",
      "country": "GR",
      "password": "$2a$10$LpgLzRcXkxU45Wwqgd.d9evdJ0wAV63LCFeLm.J78k2d1FBbnPNXG",
      "createdAt": "2022-08-16T22:54:06.419671Z"
    }
  ]
}
Listing users in GR (2nd page)
$ grpcurl -d '{"page_size":1, "page_number":2 ,"filter":{"country":"GR"}}' -plaintext localhost:50000 services.user.User/QueryUsers
{
  "users": [
    {
      "id": "b3ce8fed-d5e8-4583-8783-b95969b5bc0c",
      "email": "user2@mail.com",
      "firstName": "user2_name",
      "lastName": "user2_lname",
      "nickname": "user2_nkname",
      "country": "GR",
      "password": "$2a$10$wNV.oRXIaAjPCbZp01zrf.KBwCq98AZZ1lEAEq/0VMEaEMlUSHiN6",
      "createdAt": "2022-08-16T22:54:34.134916Z"
    }
  ]
}
Delete user
$ grpcurl -d '{"user_id":"166f7137-8884-42ab-90b2-1c2d77fc1037"}' -plaintext localhost:50000 services.user.User/DeleteUser
{
  "success": true
}
Update user
$ grpcurl -d '{"user_id":"b3ce8fed-d5e8-4583-8783-b95969b5bc0c", "fields":{"nickname":"batman"}}' -plaintext localhost:50000 services.user.User/UpdateUser
{
  "success": true
}

To stop the service type

make stop

Running tests

To run tests type

make test

To run tests with coverage report type

make report

then open the generated html file cover.html