Senior
Actualizările documentelor sosesc la serviciu message Document { string Url = 1; // URL-ul documentului, identificatorul său unic uint64 PubDate = 2; // timpul de publicare declarat al documentului uint64 FetchTime = 3; // timpul de primire a acestei actualizări a documentului, poate fi considerat ca un identificator de versiune. Perechea (Url, FetchTime) este unică. string Text = 4; // textul documentului uint64 FirstFetchTime = 5; // inițial absent, trebuie completat } Documentele pot ajunge în orice ordine (nu în ordinea în care au fost actualizate), și pot exista mesaje duplicate. Este necesar să se formeze în ieșire mesaje identice, dar cu câmpuri corectate conform următoarelor reguli (tot ce este mai jos se aplică pentru un grup de documente cu același câmp Url): Câmpul Text și FetchTime trebuie să fie cele ale documentului cu cel mai mare FetchTime primit până acum. Câmpul PubDate trebuie să fie cel al mesajului cu cel mai mic FetchTime. Câmpul FirstFetchTime trebuie să fie egal cu valoarea minimă a FetchTime. Cu alte cuvinte, în fiecare moment, luăm PubDate și FirstFetchTime din prima versiune primită până acum (dacă le sortăm după FetchTime), și Text din ultima. Interfața în cod poate fi implementată astfel: type Processor interface { Process(doc *Document) (*Document, error) } Acest cod va funcționa într-un serviciu care citește mesaje dintr-o coadă (Kafka sau similar), și scrie și rezultatul în coadă. Dacă Process returnează Null, nimic nu se scrie în coadă.
sobes.tech AI
Răspuns de la AI
Для реализации интерфейса Processor в Go нужно хранить состояние по каждому Url, чтобы на каждый входящий документ обновлять агрегированное состояние и возвращать скорректированное сообщение.
Основная идея:
- Для каждого Url хранить:
- минимальный FetchTime (для PubDate и FirstFetchTime)
- максимальный FetchTime (для Text и FetchTime)
- PubDate, Text, FirstFetchTime, соответствующие этим минимальному и максимальному FetchTime
При получении нового документа:
- Если для Url нет записи — создать с данными из документа
- Иначе обновить минимальный и максимальный FetchTime и соответствующие поля при необходимости
- Вернуть агрегированный документ с нужными полями
Пример реализации:
import (
"errors"
"sync"
)
type Document struct {
Url string
PubDate uint64
FetchTime uint64
Text string
FirstFetchTime uint64
}
type Processor interface {
Process(doc *Document) (*Document, error)
}
type docState struct {
minFetchTime uint64
maxFetchTime uint64
pubDate uint64
text string
firstFetch uint64
}
type processorImpl struct {
mu sync.Mutex
state map[string]*docState
}
func NewProcessor() Processor {
return &processorImpl{
state: make(map[string]*docState),
}
}
func (p *processorImpl) Process(doc *Document) (*Document, error) {
if doc == nil {
return nil, errors.New("input document is nil")
}
p.mu.Lock()
defer p.mu.Unlock()
st, ok := p.state[doc.Url]
if !ok {
// первый документ для данного Url
p.state[doc.Url] = &docState{
minFetchTime: doc.FetchTime,
maxFetchTime: doc.FetchTime,
pubDate: doc.PubDate,
text: doc.Text,
firstFetch: doc.FetchTime,
}
return &Document{
Url: doc.Url,
PubDate: doc.PubDate,
FetchTime: doc.FetchTime,
Text: doc.Text,
FirstFetchTime: doc.FetchTime,
}, nil
}
updated := false
// Обновляем минимальный FetchTime и PubDate, FirstFetchTime
if doc.FetchTime < st.minFetchTime {
st.minFetchTime = doc.FetchTime
st.pubDate = doc.PubDate
st.firstFetch = doc.FetchTime
updated = true
}
// Обновляем максимальный FetchTime и Text
if doc.FetchTime > st.maxFetchTime {
st.maxFetchTime = doc.FetchTime
st.text = doc.Text
updated = true
}
// Если пришло сообщение с FetchTime, который уже есть, но текст или PubDate отличаются,
// можно игнорировать, так как пара (Url, FetchTime) уникальна, либо обновлять по логике.
if !updated {
// Данные не изменились, можно вернуть nil, чтобы не писать в очередь
return nil, nil
}
return &Document{
Url: doc.Url,
PubDate: st.pubDate,
FetchTime: st.maxFetchTime,
Text: st.text,
FirstFetchTime: st.firstFetch,
}, nil
}
Таким образом, сервис будет поддерживать актуальное агрегированное состояние для каждого Url и возвращать скорректированные документы согласно правилам.