Added core support for DB synchronization.
This commit is contained in:
parent
9c007b3de5
commit
d6edd3f11d
@ -50,7 +50,10 @@ public class MediaLibrary {
|
||||
staleBookmarks.each { dbapi.delete(it) } } }
|
||||
|
||||
public def rescanLibrary() {
|
||||
def results = [ total: 0, ignored: 0, new: 0]
|
||||
def results = [ total: 0, ignored: 0, new: 0, present: 0, absent: 0]
|
||||
|
||||
List<MediaFile> missingFiles = dbapi.getMediaFiles()
|
||||
List<MediaFile> foundFiles = []
|
||||
|
||||
Date startDate = new Date()
|
||||
libraryRoot.eachFileRecurse { file ->
|
||||
@ -60,7 +63,23 @@ public class MediaLibrary {
|
||||
|
||||
results.total++
|
||||
if (!mf) results.ignored++
|
||||
else if (mf.dateAdded > startDate) results.new++ }
|
||||
else {
|
||||
foundFiles << mf
|
||||
if (missingFiles.contains(mf)) missingFiles.remove(mf)
|
||||
if (mf.dateAdded > startDate) results.new++ } }
|
||||
|
||||
foundFiles.each { mf ->
|
||||
if (!mf.presentLocally) {
|
||||
mf.presentLocally = true
|
||||
dbapi.update(mf) } }
|
||||
|
||||
missingFiles.each { mf ->
|
||||
if (mf.presentLocally) {
|
||||
mf.presentLocally = false
|
||||
dbapi.update(mf) } }
|
||||
|
||||
results.present = foundFiles.size()
|
||||
results.absent = missingFiles.size()
|
||||
|
||||
return results }
|
||||
|
||||
|
@ -927,4 +927,72 @@ public class DbApi {
|
||||
|
||||
static def getInstanceFields(Class modelClass) {
|
||||
return modelClass.fields.findAll { !Modifier.isStatic(it.modifiers) } }
|
||||
|
||||
/// ### DB Sync/Replication
|
||||
|
||||
public def diffWith(DbApi that) {
|
||||
|
||||
def results = [
|
||||
ours: [ modelIds: [:], associations: [:] ],
|
||||
theirs:[ modelIds: [:], associations: [:] ] ]
|
||||
|
||||
[Album, Artist, Image, MediaFile, Playlist, Bookmark,
|
||||
Tag].each { modelClass ->
|
||||
|
||||
List<UUID> ourIds = this.getAllIds(modelClass)
|
||||
List<UUID> theirIds = that.getAllIds(modelClass)
|
||||
|
||||
results.ours.modelIds[modelClass] = ourIds - theirIds
|
||||
results.theirs.modelIds[modelClass] = theirIds - ourIds }
|
||||
|
||||
['albums_images', 'albums_media_files', 'artists_albums',
|
||||
'artists_images', 'artists_media_files', 'media_files_tags',
|
||||
'playlists_media_files'].each { tableName ->
|
||||
|
||||
def query = 'SELECT * FROM ' + tableName;
|
||||
def allOurRows = this.sql.rows(query)
|
||||
def allTheirRows = that.sql.rows(query)
|
||||
|
||||
def ourRows = allOurRows.clone()
|
||||
def theirRows = allTheirRows.clone()
|
||||
|
||||
allOurRows.each { ourRow ->
|
||||
allTheirRows.each { theirRow ->
|
||||
if (ourRow[0] == theirRow[0]) {
|
||||
ourRows.remove(ourRow)
|
||||
theirRows.remove(theirRow) } } }
|
||||
|
||||
results.ours.associations[tableName] = ourRows
|
||||
results.theirs.associations[tableName] = theirRows }
|
||||
|
||||
return results }
|
||||
|
||||
public def ingestDiff(DbApi that, def diff) {
|
||||
|
||||
diff.modelIds.each { modelClass, ids ->
|
||||
ids.each { id -> this.create(that.getById(modelClass, id)) } }
|
||||
|
||||
diff.associations.each { tableName, rows ->
|
||||
String placeholders = null
|
||||
String query = null
|
||||
rows.each { row ->
|
||||
if (!placeholders)
|
||||
placeholders = (1..row.size()).collect { '?' }.join(', ')
|
||||
|
||||
if (!query)
|
||||
query = "INSERT INTO ${tableName} VALUES (${placeholders})"
|
||||
|
||||
logger.debug("Adding association.\n\tSQL: {}\n\tPARAMS: {}",
|
||||
query, row.values() as List)
|
||||
this.sql.executeInsert(query, row.values() as List) } } }
|
||||
|
||||
public def syncWith(DbApi that, boolean pull = true,
|
||||
boolean push = false) {
|
||||
def diff = this.diffWith(that)
|
||||
|
||||
if (pull) this.ingestDiff(that, diff.theirs)
|
||||
if (push) that.ingestDiff(this, diff.ours)
|
||||
|
||||
return diff }
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user