internal/storage/postgres/storage.go
func (s *Storage) SetValue(ctx context.Context, accessToken string, key, value string) (map[string]string, error) {
	span, ctx := opentracing.StartSpanFromContext(ctx, "postgres.storage.set-value")
	defer span.Finish()

	var err error
	if accessToken == "" {
		return nil, storage.ErrMissingAccessToken
	}

	entity := &sessionEntity{
		AccessToken: accessToken,
	}
	selectQuery := `
		SELECT bag
		FROM ` + s.schema + `.` + s.table + `
		WHERE access_token = $1
		FOR UPDATE
	`
	updateQuery := `
		UPDATE ` + s.schema + `.` + s.table + `
		SET
			bag = $2
		WHERE access_token = $1
	`

	tx, err := s.db.BeginTx(ctx, nil)
	if err != nil {
		tx.Rollback()
		return nil, err
	}

	startSelect := time.Now()
	err = tx.QueryRowContext(ctx, selectQuery, accessToken).Scan(
		&entity.Bag,
	)
	s.incQueries(prometheus.Labels{"query": "set_value_select"}, startSelect)
	if err != nil {
		s.incError(prometheus.Labels{"query": "set_value_select"})
		tx.Rollback()
		if err == sql.ErrNoRows {
			return nil, storage.ErrSessionNotFound
		}
		return nil, err
	}

	entity.Bag.Set(key, value)

	startUpdate := time.Now()
	_, err = tx.ExecContext(ctx, updateQuery, accessToken, entity.Bag)
	s.incQueries(prometheus.Labels{"query": "set_value_update"}, startUpdate)
	if err != nil {
		s.incError(prometheus.Labels{"query": "set_value_update"})
		tx.Rollback()
		return nil, err
	}

	tx.Commit()

	return entity.Bag, nil
}
func (s *Storage) SetValue(ctx context.Context, accessToken string, key, value string) (map[string]string, error) {
	span, ctx := opentracing.StartSpanFromContext(ctx, "postgres.storage.set-value")
	defer span.Finish()

	var err error
	if accessToken == "" {
		return nil, storage.ErrMissingAccessToken
	}

	entity := &sessionEntity{
		AccessToken: accessToken,
	}
	selectQuery := `
		SELECT bag
		FROM ` + s.schema + `.` + s.table + `
		WHERE access_token = $1
		FOR UPDATE
	`
	updateQuery := `
		UPDATE ` + s.schema + `.` + s.table + `
		SET
			bag = $2
		WHERE access_token = $1
	`

	tx, err := s.db.BeginTx(ctx, nil)
	if err != nil {
		tx.Rollback()
		return nil, err
	}

	startSelect := time.Now()
	err = tx.QueryRowContext(ctx, selectQuery, accessToken).Scan(
		&entity.Bag,
	)
	s.incQueries(prometheus.Labels{"query": "set_value_select"}, startSelect)
	if err != nil {
		s.incError(prometheus.Labels{"query": "set_value_select"})
		tx.Rollback()
		if err == sql.ErrNoRows {
			return nil, storage.ErrSessionNotFound
		}
		return nil, err
	}

	entity.Bag.Set(key, value)

	startUpdate := time.Now()
	_, err = tx.ExecContext(ctx, updateQuery, accessToken, entity.Bag)
	s.incQueries(prometheus.Labels{"query": "set_value_update"}, startUpdate)
	if err != nil {
		s.incError(prometheus.Labels{"query": "set_value_update"})
		tx.Rollback()
		return nil, err
	}

	tx.Commit()

	return entity.Bag, nil
}
// SetValue implements storage interface.