mirror of
https://gitlab.com/ultrasonic/ultrasonic.git
synced 2025-05-05 18:11:04 +03:00
Store loaded indexes in persistent storage.
Signed-off-by: Yahor Berdnikau <egorr.berd@gmail.com>
This commit is contained in:
parent
63715aab18
commit
423461c3ba
60
cache/src/main/kotlin/org/moire/ultrasonic/cache/serializers/ArtistSerializer.kt
vendored
Normal file
60
cache/src/main/kotlin/org/moire/ultrasonic/cache/serializers/ArtistSerializer.kt
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
@file:JvmMultifileClass
|
||||
@file:JvmName("DomainSerializers")
|
||||
package org.moire.ultrasonic.cache.serializers
|
||||
|
||||
import com.twitter.serial.serializer.CollectionSerializers
|
||||
import com.twitter.serial.serializer.ObjectSerializer
|
||||
import com.twitter.serial.serializer.SerializationContext
|
||||
import com.twitter.serial.stream.SerializerDefs
|
||||
import com.twitter.serial.stream.SerializerInput
|
||||
import com.twitter.serial.stream.SerializerOutput
|
||||
import org.moire.ultrasonic.domain.Artist
|
||||
|
||||
private const val SERIALIZER_VERSION = 1
|
||||
|
||||
/**
|
||||
* Serializer/deserializer for [Artist] domain entity.
|
||||
*/
|
||||
val artistSerializer get() = object : ObjectSerializer<Artist>(SERIALIZER_VERSION) {
|
||||
override fun serializeObject(
|
||||
context: SerializationContext,
|
||||
output: SerializerOutput<out SerializerOutput<*>>,
|
||||
item: Artist
|
||||
) {
|
||||
output.writeString(item.id)
|
||||
.writeString(item.name)
|
||||
.writeString(item.index)
|
||||
.writeString(item.coverArt)
|
||||
.apply {
|
||||
val albumCount = item.albumCount
|
||||
if (albumCount != null) writeLong(albumCount) else writeNull()
|
||||
}
|
||||
.writeInt(item.closeness)
|
||||
}
|
||||
|
||||
override fun deserializeObject(
|
||||
context: SerializationContext,
|
||||
input: SerializerInput,
|
||||
versionNumber: Int
|
||||
): Artist? {
|
||||
if (versionNumber != SERIALIZER_VERSION) return null
|
||||
|
||||
val id = input.readString()
|
||||
val name = input.readString()
|
||||
val index = input.readString()
|
||||
val coverArt = input.readString()
|
||||
val albumCount = if (input.peekType() == SerializerDefs.TYPE_NULL) {
|
||||
input.readNull()
|
||||
null
|
||||
} else {
|
||||
input.readLong()
|
||||
}
|
||||
val closeness = input.readInt()
|
||||
return Artist(id, name, index, coverArt, albumCount, closeness)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializer/deserializer for list of [Artist] domain entities.
|
||||
*/
|
||||
val artistListSerializer = CollectionSerializers.getListSerializer(artistSerializer)
|
44
cache/src/main/kotlin/org/moire/ultrasonic/cache/serializers/IndexesSerializer.kt
vendored
Normal file
44
cache/src/main/kotlin/org/moire/ultrasonic/cache/serializers/IndexesSerializer.kt
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
@file:JvmMultifileClass
|
||||
@file:JvmName("DomainSerializers")
|
||||
package org.moire.ultrasonic.cache.serializers
|
||||
|
||||
import com.twitter.serial.serializer.CollectionSerializers
|
||||
import com.twitter.serial.serializer.ObjectSerializer
|
||||
import com.twitter.serial.serializer.SerializationContext
|
||||
import com.twitter.serial.stream.SerializerInput
|
||||
import com.twitter.serial.stream.SerializerOutput
|
||||
import org.moire.ultrasonic.domain.Artist
|
||||
import org.moire.ultrasonic.domain.Indexes
|
||||
|
||||
private const val SERIALIZATION_VERSION = 1
|
||||
|
||||
val indexesSerializer get() = object : ObjectSerializer<Indexes>(SERIALIZATION_VERSION) {
|
||||
override fun serializeObject(
|
||||
context: SerializationContext,
|
||||
output: SerializerOutput<out SerializerOutput<*>>,
|
||||
item: Indexes
|
||||
) {
|
||||
output.writeLong(item.lastModified)
|
||||
.writeString(item.ignoredArticles)
|
||||
.writeObject<MutableList<Artist>>(context, item.shortcuts,
|
||||
CollectionSerializers.getListSerializer(artistSerializer))
|
||||
.writeObject<MutableList<Artist>>(context, item.artists,
|
||||
CollectionSerializers.getListSerializer(artistSerializer))
|
||||
}
|
||||
|
||||
override fun deserializeObject(
|
||||
context: SerializationContext,
|
||||
input: SerializerInput,
|
||||
versionNumber: Int
|
||||
): Indexes? {
|
||||
if (versionNumber != SERIALIZATION_VERSION) return null
|
||||
|
||||
val lastModified = input.readLong()
|
||||
val ignoredArticles = input.readString() ?: return null
|
||||
val shortcutsList = input.readObject(context,
|
||||
CollectionSerializers.getListSerializer(artistSerializer)) ?: return null
|
||||
val artistsList = input.readObject(context,
|
||||
CollectionSerializers.getListSerializer(artistSerializer)) ?: return null
|
||||
return Indexes(lastModified, ignoredArticles, shortcutsList, artistsList)
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package org.moire.ultrasonic.cache
|
||||
|
||||
import com.nhaarman.mockito_kotlin.mock
|
||||
import com.twitter.serial.util.SerializationUtils
|
||||
import org.amshove.kluent.`it returns`
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
@ -31,4 +32,9 @@ abstract class BaseStorageTest {
|
||||
}
|
||||
|
||||
protected val storageDir get() = File(mockDirectories.getInternalDataDir(), STORAGE_DIR_NAME)
|
||||
|
||||
protected fun validateSerializedData(index: Int = 0) {
|
||||
val serializedFileBytes = storageDir.listFiles()[index].readBytes()
|
||||
SerializationUtils.validateSerializedData(serializedFileBytes)
|
||||
}
|
||||
}
|
||||
|
57
cache/src/test/kotlin/org/moire/ultrasonic/cache/serializers/ArtistSerializerTest.kt
vendored
Normal file
57
cache/src/test/kotlin/org/moire/ultrasonic/cache/serializers/ArtistSerializerTest.kt
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
package org.moire.ultrasonic.cache.serializers
|
||||
|
||||
import org.amshove.kluent.`should equal`
|
||||
import org.junit.Test
|
||||
import org.moire.ultrasonic.cache.BaseStorageTest
|
||||
import org.moire.ultrasonic.domain.Artist
|
||||
|
||||
/**
|
||||
* [Artist] serializers test.
|
||||
*/
|
||||
class ArtistSerializerTest : BaseStorageTest() {
|
||||
@Test
|
||||
fun `Should correctly serialize Artist object`() {
|
||||
val item = Artist("id", "name", "index", "coverArt", 1, 0)
|
||||
|
||||
storage.store("some-name", item, artistSerializer)
|
||||
|
||||
validateSerializedData()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Should correctly deserialize Artist object`() {
|
||||
val itemName = "some-name"
|
||||
val item = Artist("id", "name", "index", "coverArt", null, 0)
|
||||
storage.store(itemName, item, artistSerializer)
|
||||
|
||||
val loadedItem = storage.load(itemName, artistSerializer)
|
||||
|
||||
loadedItem `should equal` item
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Should correctly serialize list of Artists`() {
|
||||
val itemsList = listOf(
|
||||
Artist(id = "1"),
|
||||
Artist(id = "2", name = "some")
|
||||
)
|
||||
|
||||
storage.store("some-name", itemsList, artistListSerializer)
|
||||
|
||||
validateSerializedData()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Should correctly deserialize list of Artists`() {
|
||||
val name = "some-name"
|
||||
val itemsList = listOf(
|
||||
Artist(id = "1"),
|
||||
Artist(id = "2", name = "some")
|
||||
)
|
||||
storage.store(name, itemsList, artistListSerializer)
|
||||
|
||||
val loadedItems = storage.load(name, artistListSerializer)
|
||||
|
||||
loadedItems `should equal` itemsList
|
||||
}
|
||||
}
|
40
cache/src/test/kotlin/org/moire/ultrasonic/cache/serializers/IndexesSerializerTest.kt
vendored
Normal file
40
cache/src/test/kotlin/org/moire/ultrasonic/cache/serializers/IndexesSerializerTest.kt
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
package org.moire.ultrasonic.cache.serializers
|
||||
|
||||
import org.amshove.kluent.`should equal`
|
||||
import org.junit.Test
|
||||
import org.moire.ultrasonic.cache.BaseStorageTest
|
||||
import org.moire.ultrasonic.domain.Artist
|
||||
import org.moire.ultrasonic.domain.Indexes
|
||||
|
||||
/**
|
||||
* Test [Indexes] domain entity serializer.
|
||||
*/
|
||||
class IndexesSerializerTest : BaseStorageTest() {
|
||||
@Test
|
||||
fun `Should correctly serialize Indexes object`() {
|
||||
val item = Indexes(220L, "", mutableListOf(
|
||||
Artist("12")
|
||||
), mutableListOf(
|
||||
Artist("233", "some")
|
||||
))
|
||||
|
||||
storage.store("some-name", item, indexesSerializer)
|
||||
|
||||
validateSerializedData()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Should correctly deserialize Indexes object`() {
|
||||
val name = "some-name"
|
||||
val item = Indexes(220L, "", mutableListOf(
|
||||
Artist("12")
|
||||
), mutableListOf(
|
||||
Artist("233", "some")
|
||||
))
|
||||
storage.store(name, item, indexesSerializer)
|
||||
|
||||
val loadedItem = storage.load(name, indexesSerializer)
|
||||
|
||||
loadedItem `should equal` item
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
package org.moire.ultrasonic.cache.serializers
|
||||
|
||||
import com.twitter.serial.util.SerializationUtils
|
||||
import org.amshove.kluent.`should equal`
|
||||
import org.junit.Test
|
||||
import org.moire.ultrasonic.cache.BaseStorageTest
|
||||
@ -16,8 +15,7 @@ class MusicFolderSerializerTest : BaseStorageTest() {
|
||||
|
||||
storage.store("some-name", item, musicFolderSerializer)
|
||||
|
||||
val serializedFileBytes = storageDir.listFiles()[0].readBytes()
|
||||
SerializationUtils.validateSerializedData(serializedFileBytes)
|
||||
validateSerializedData()
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -40,8 +38,7 @@ class MusicFolderSerializerTest : BaseStorageTest() {
|
||||
|
||||
storage.store("some-name", itemsList, musicFolderListSerializer)
|
||||
|
||||
val serializedFileBytes = storageDir.listFiles()[0].readBytes()
|
||||
SerializationUtils.validateSerializedData(serializedFileBytes)
|
||||
validateSerializedData()
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -120,6 +120,7 @@ public class RESTMusicService implements MusicService {
|
||||
private static final String TAG = RESTMusicService.class.getSimpleName();
|
||||
|
||||
private static final String MUSIC_FOLDER_STORAGE_NAME = "music_folder";
|
||||
private static final String INDEXES_STORAGE_NAME = "indexes";
|
||||
|
||||
private final SubsonicAPIClient subsonicAPIClient;
|
||||
private final PermanentFileStorage fileStorage;
|
||||
@ -155,8 +156,8 @@ public class RESTMusicService implements MusicService {
|
||||
public List<MusicFolder> getMusicFolders(boolean refresh,
|
||||
Context context,
|
||||
ProgressListener progressListener) throws Exception {
|
||||
List<MusicFolder> cachedMusicFolders = fileStorage
|
||||
.load(MUSIC_FOLDER_STORAGE_NAME, DomainSerializers.getMusicFolderListSerializer());
|
||||
List<MusicFolder> cachedMusicFolders = fileStorage.load(MUSIC_FOLDER_STORAGE_NAME,
|
||||
DomainSerializers.getMusicFolderListSerializer());
|
||||
if (cachedMusicFolders != null && !refresh) {
|
||||
return cachedMusicFolders;
|
||||
}
|
||||
@ -177,7 +178,8 @@ public class RESTMusicService implements MusicService {
|
||||
boolean refresh,
|
||||
Context context,
|
||||
ProgressListener progressListener) throws Exception {
|
||||
Indexes cachedIndexes = readCachedIndexes(context, musicFolderId);
|
||||
Indexes cachedIndexes = fileStorage.load(INDEXES_STORAGE_NAME,
|
||||
DomainSerializers.getIndexesSerializer());
|
||||
if (cachedIndexes != null && !refresh) {
|
||||
return cachedIndexes;
|
||||
}
|
||||
@ -188,25 +190,10 @@ public class RESTMusicService implements MusicService {
|
||||
checkResponseSuccessful(response);
|
||||
|
||||
Indexes indexes = APIIndexesConverter.toDomainEntity(response.body().getIndexes());
|
||||
writeCachedIndexes(context, indexes, musicFolderId);
|
||||
fileStorage.store(INDEXES_STORAGE_NAME, indexes, DomainSerializers.getIndexesSerializer());
|
||||
return indexes;
|
||||
}
|
||||
|
||||
private static Indexes readCachedIndexes(Context context, String musicFolderId) {
|
||||
String filename = getCachedIndexesFilename(context, musicFolderId);
|
||||
return FileUtil.deserialize(context, filename);
|
||||
}
|
||||
|
||||
private static void writeCachedIndexes(Context context, Indexes indexes, String musicFolderId) {
|
||||
String filename = getCachedIndexesFilename(context, musicFolderId);
|
||||
FileUtil.serialize(context, indexes, filename);
|
||||
}
|
||||
|
||||
private static String getCachedIndexesFilename(Context context, String musicFolderId) {
|
||||
String s = Util.getRestUrl(context, null) + musicFolderId;
|
||||
return String.format(Locale.US, "indexes-%d.ser", Math.abs(s.hashCode()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Indexes getArtists(boolean refresh,
|
||||
Context context,
|
||||
|
Loading…
x
Reference in New Issue
Block a user