Нужен in-memory кеш, который по ID аккаунта отдаёт профиль вместе со списком
покупок. Список покупок меняется точечно, без перезаписи всего профиля.
type AccountProfile struct {
ID string
DisplayName string
Purchases []Purchase
}
type Purchase struct {
ID string
PlacedAt time.Time
ModifiedAt time.Time
Items any
}
var (
ErrNotFound = errors.New("account not found")
ErrPurchaseNotFound = errors.New("purchase not found")
ErrPurchaseExists = errors.New("purchase already exists")
)
// NewCache: каждая запись живёт ttl с момента Set. now — часы (nil → time.Now).
func NewCache(ttl time.Duration, now func() time.Time) *Cache
func (c *Cache) Set(p AccountProfile)
func (c *Cache) Get(id string) (AccountProfile, bool)
func (c *Cache) AddPurchase(accountID string, p Purchase) error
func (c *Cache) UpdatePurchase(accountID string, p Purchase) error
func (c *Cache) DeletePurchase(accountID, purchaseID string) error
Требования
Set кладёт профиль (или заменяет существующий) и запускает TTL заново.
Запись живёт, пока now() < момент Set + ttl.
Get протухшей или отсутствующей записи возвращает false. Get TTL не
продлевает.
AddPurchase добавляет покупку в конец списка. Покупка с таким ID уже
есть — ErrPurchaseExists.
UpdatePurchase заменяет покупку с тем же ID на месте, не меняя порядок.
Нет такой — ErrPurchaseNotFound.
DeletePurchase удаляет покупку, порядок остальных сохраняется. Нет такой —
ErrPurchaseNotFound.
- Операции с покупками у отсутствующего или протухшего аккаунта возвращают
ErrNotFound и TTL не продлевают.
- Кеш не делит память с вызывающим. Изменения слайса, переданного в
Set,
или профиля, полученного из Get, не влияют на кеш, и наоборот. Поле Items
копировать вглубь не нужно: считаем его неизменяемым.
- Кеш безопасен для конкурентного использования, код проходит
go test -race.
Пример
c := NewCache(10*time.Minute, nil)
c.Set(AccountProfile{ID: "u1", DisplayName: "Nina"})
_ = c.AddPurchase("u1", Purchase{ID: "p1"})
_ = c.AddPurchase("u1", Purchase{ID: "p2"})
_ = c.DeletePurchase("u1", "p1")
p, ok := c.Get("u1") // ok == true, p.Purchases == [p2]
Устно: какие тестовые сценарии ты бы написал для этого кеша? Что будет с
памятью, если протухшие записи никто не читает, и как их чистить?
Разбор и эталонное решение — после своей попытки: на собеседовании подсказок не будет.
Сначала попробуй сам — подсказки не дают готовый ответ.