mirror of
https://git.sr.ht/~phw/scotty
synced 2025-04-25 05:47:57 +02:00
listenbrainz: fetch listens in reverse listen time order
This allows parallel import
This commit is contained in:
parent
cde9b28c28
commit
4bf0f2c81d
6 changed files with 34 additions and 20 deletions
|
@ -1,5 +1,9 @@
|
||||||
# Scotty Changelog
|
# Scotty Changelog
|
||||||
|
|
||||||
|
## 0.3.0 - unreleased
|
||||||
|
- listenbrainz: fetch listens in reverse listen time order
|
||||||
|
|
||||||
|
|
||||||
## 0.2.0 - 2023-11-28
|
## 0.2.0 - 2023-11-28
|
||||||
- lastfm: support for scrobble and love export/import
|
- lastfm: support for scrobble and love export/import
|
||||||
- jspf: consider loved track MBID
|
- jspf: consider loved track MBID
|
||||||
|
|
|
@ -53,6 +53,8 @@ func TestGetListens(t *testing.T) {
|
||||||
|
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
assert.Equal(2, result.Payload.Count)
|
assert.Equal(2, result.Payload.Count)
|
||||||
|
assert.Equal(int64(1699718723), result.Payload.LatestListenTimestamp)
|
||||||
|
assert.Equal(int64(1152911863), result.Payload.OldestListenTimestamp)
|
||||||
require.Len(t, result.Payload.Listens, 2)
|
require.Len(t, result.Payload.Listens, 2)
|
||||||
assert.Equal("Shadowplay", result.Payload.Listens[0].TrackMetadata.TrackName)
|
assert.Equal("Shadowplay", result.Payload.Listens[0].TrackMetadata.TrackName)
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,20 +46,19 @@ func (b *ListenBrainzApiBackend) FinishImport() error { return nil }
|
||||||
|
|
||||||
func (b *ListenBrainzApiBackend) ExportListens(oldestTimestamp time.Time, results chan models.ListensResult, progress chan models.Progress) {
|
func (b *ListenBrainzApiBackend) ExportListens(oldestTimestamp time.Time, results chan models.ListensResult, progress chan models.Progress) {
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
maxTime := startTime
|
minTime := oldestTimestamp
|
||||||
minTime := time.Unix(0, 0)
|
if minTime.Unix() < 1 {
|
||||||
|
minTime = time.Unix(1, 0)
|
||||||
|
}
|
||||||
|
|
||||||
totalDuration := startTime.Sub(oldestTimestamp)
|
totalDuration := startTime.Sub(minTime)
|
||||||
|
|
||||||
defer close(results)
|
defer close(results)
|
||||||
|
|
||||||
// FIXME: Optimize by fetching the listens in reverse listen time order
|
|
||||||
listens := make(models.ListensList, 0, 2*MaxItemsPerGet)
|
|
||||||
p := models.Progress{Total: int64(totalDuration.Seconds())}
|
p := models.Progress{Total: int64(totalDuration.Seconds())}
|
||||||
|
|
||||||
out:
|
|
||||||
for {
|
for {
|
||||||
result, err := b.client.GetListens(b.username, maxTime, minTime)
|
result, err := b.client.GetListens(b.username, time.Now(), minTime)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
progress <- p.Complete()
|
progress <- p.Complete()
|
||||||
results <- models.ListensResult{Error: err}
|
results <- models.ListensResult{Error: err}
|
||||||
|
@ -68,31 +67,39 @@ out:
|
||||||
|
|
||||||
count := len(result.Payload.Listens)
|
count := len(result.Payload.Listens)
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
break
|
if minTime.Unix() < result.Payload.OldestListenTimestamp {
|
||||||
|
minTime = time.Unix(result.Payload.OldestListenTimestamp, 0)
|
||||||
|
totalDuration = startTime.Sub(minTime)
|
||||||
|
p.Total = int64(totalDuration.Seconds())
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set maxTime to the oldest returned listen
|
// Set minTime to the newest returned listen
|
||||||
maxTime = time.Unix(result.Payload.Listens[count-1].ListenedAt, 0)
|
minTime = time.Unix(result.Payload.Listens[0].ListenedAt, 0)
|
||||||
remainingTime := maxTime.Sub(oldestTimestamp)
|
remainingTime := startTime.Sub(minTime)
|
||||||
|
|
||||||
|
listens := make(models.ListensList, 0, count)
|
||||||
|
|
||||||
for _, listen := range result.Payload.Listens {
|
for _, listen := range result.Payload.Listens {
|
||||||
if listen.ListenedAt > oldestTimestamp.Unix() {
|
if listen.ListenedAt > oldestTimestamp.Unix() {
|
||||||
listens = append(listens, listen.AsListen())
|
listens = append(listens, listen.AsListen())
|
||||||
} else {
|
} else {
|
||||||
// result contains listens older then oldestTimestamp,
|
// result contains listens older then oldestTimestamp
|
||||||
// we can stop requesting more
|
break
|
||||||
p.Total = int64(startTime.Sub(time.Unix(listen.ListenedAt, 0)).Seconds())
|
|
||||||
break out
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sort.Sort(listens)
|
||||||
p.Elapsed = int64(totalDuration.Seconds() - remainingTime.Seconds())
|
p.Elapsed = int64(totalDuration.Seconds() - remainingTime.Seconds())
|
||||||
progress <- p
|
progress <- p
|
||||||
|
results <- models.ListensResult{Listens: listens, OldestTimestamp: minTime}
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.Sort(listens)
|
results <- models.ListensResult{OldestTimestamp: minTime}
|
||||||
progress <- p.Complete()
|
progress <- p.Complete()
|
||||||
results <- models.ListensResult{Listens: listens, OldestTimestamp: oldestTimestamp}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *ListenBrainzApiBackend) ImportListens(export models.ListensResult, importResult models.ImportResult, progress chan models.Progress) (models.ImportResult, error) {
|
func (b *ListenBrainzApiBackend) ImportListens(export models.ListensResult, importResult models.ImportResult, progress chan models.Progress) (models.ImportResult, error) {
|
||||||
|
|
|
@ -36,6 +36,7 @@ type GetListenPayload struct {
|
||||||
Count int `json:"count"`
|
Count int `json:"count"`
|
||||||
UserName string `json:"user_id"`
|
UserName string `json:"user_id"`
|
||||||
LatestListenTimestamp int64 `json:"latest_listen_ts"`
|
LatestListenTimestamp int64 `json:"latest_listen_ts"`
|
||||||
|
OldestListenTimestamp int64 `json:"oldest_listen_ts"`
|
||||||
Listens []Listen `json:"listens"`
|
Listens []Listen `json:"listens"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
"payload": {
|
"payload": {
|
||||||
"count": 2,
|
"count": 2,
|
||||||
"latest_listen_ts": 1699718723,
|
"latest_listen_ts": 1699718723,
|
||||||
|
"oldest_listen_ts": 1152911863,
|
||||||
"listens": [
|
"listens": [
|
||||||
{
|
{
|
||||||
"inserted_at": 1699719320,
|
"inserted_at": 1699719320,
|
||||||
|
|
|
@ -122,15 +122,14 @@ func (b *SpotifyApiBackend) ExportListens(oldestTimestamp time.Time, results cha
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
listens := make(models.ListensList, 0, len(result.Items))
|
listens := make(models.ListensList, 0, count)
|
||||||
|
|
||||||
for _, listen := range result.Items {
|
for _, listen := range result.Items {
|
||||||
l := listen.AsListen()
|
l := listen.AsListen()
|
||||||
if l.ListenedAt.Unix() > oldestTimestamp.Unix() {
|
if l.ListenedAt.Unix() > oldestTimestamp.Unix() {
|
||||||
listens = append(listens, l)
|
listens = append(listens, l)
|
||||||
} else {
|
} else {
|
||||||
// result contains listens older then oldestTimestamp,
|
// result contains listens older then oldestTimestamp
|
||||||
// we can stop requesting more
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue