Sobes.tech
Junior — Senior

Optimization and improvement of an existing service

livecode

Task condition

It is necessary to review the service code, identify problematic areas, and make corrections.

package service

import (
  "context"
  "encoding/json"
  "io"
  "net/http"
  "strconv"

  "github.com/jackc/pgx/v5"
)

// documentRepository is the repository for interacting with the database.
type documentRepository interface {
  SavePDF(tx pgx.Tx, data []byte)
  SetValueForUser(tx pgx.Tx, userID uint64, columnName string, flagValue any)
}

// pdfService is the interface of this service for external consumers.
type pdfService interface {
  GenerateDocumentForUser(userID uint64) error
}

// Service is the structure-implementation of the service.
type Service struct {
  conn     pgx.Conn
  docRepo  documentRepository
}
/*
GenerateDocumentForUser creates a PDF document for the user and saves it to the database.
Marks the user with the flag pdf_generated – so as not to generate the file next time.
Does everything within a transaction.
*/
func (s Service) GenerateDocumentForUser(userID uint64) error {
  ctx := context.Background()

  tx, err := s.conn.Begin(ctx)
  if err != nil {
    panic("cannot start tx!")
  }

  data, err := getDataFromExternalService(userID)
  if err != nil {
    return err
  }

  pdf := generatePDF(data)

  s.docRepo.SavePDF(tx, pdf)
  s.docRepo.SetValueForUser(tx, userID, "pdf_generated", true)

  return tx.Commit(ctx)
}
type data struct {
  Phone string `json:"phone"`
  INN   string `json:"inn"`
}

func getDataFromExternalService(userID uint64) (data, error) {
  var d data

  resp, err := http.Get("http://nalog.external.provider/info/" + strconv.Itoa(int(userID)))
  if err != nil {
    return d, err
  }

  bytes, _ := io.ReadAll(resp.Body)

  json.Unmarshal(bytes, &d)

  return d, nil
}

func generatePDF(data data) []byte {
  // external lib for creating pdf
  return []byte{}
}