mirror of
https://github.com/ente-io/ente.git
synced 2025-08-13 17:57:31 +00:00
feat: add status, fix xml parsing
This commit is contained in:
@@ -28,22 +28,23 @@ class UploadLocksDB {
|
|||||||
columnFileKey: "file_key",
|
columnFileKey: "file_key",
|
||||||
columnObjectKey: "object_key",
|
columnObjectKey: "object_key",
|
||||||
columnCompleteUrl: "complete_url",
|
columnCompleteUrl: "complete_url",
|
||||||
columnCompletionStatus: "completion_status",
|
columnStatus: "status",
|
||||||
columnPartSize: "part_size",
|
columnPartSize: "part_size",
|
||||||
);
|
);
|
||||||
|
|
||||||
static const _trackStatus = (
|
|
||||||
pending: "pending",
|
|
||||||
completed: "completed",
|
|
||||||
);
|
|
||||||
|
|
||||||
static const _partsTable = (
|
static const _partsTable = (
|
||||||
table: "upload_parts",
|
table: "upload_parts",
|
||||||
columnObjectKey: "object_key",
|
columnObjectKey: "object_key",
|
||||||
columnPartNumber: "part_number",
|
columnPartNumber: "part_number",
|
||||||
columnPartUrl: "part_url",
|
columnPartUrl: "part_url",
|
||||||
|
columnPartETag: "part_etag",
|
||||||
columnPartStatus: "part_status",
|
columnPartStatus: "part_status",
|
||||||
);
|
);
|
||||||
|
static const trackStatus = (
|
||||||
|
pending: "pending",
|
||||||
|
uploaded: "uploaded",
|
||||||
|
completed: "completed",
|
||||||
|
);
|
||||||
static const _partStatus = (
|
static const _partStatus = (
|
||||||
pending: "pending",
|
pending: "pending",
|
||||||
uploaded: "uploaded",
|
uploaded: "uploaded",
|
||||||
@@ -98,10 +99,6 @@ class UploadLocksDB {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// drop
|
|
||||||
// await db.execute('DROP TABLE IF EXISTS ${_trackUploadTable.table}');
|
|
||||||
// await db.execute('DROP TABLE IF EXISTS ${_partsTable.table}');
|
|
||||||
|
|
||||||
await db.execute(
|
await db.execute(
|
||||||
'''
|
'''
|
||||||
CREATE TABLE ${_trackUploadTable.table} (
|
CREATE TABLE ${_trackUploadTable.table} (
|
||||||
@@ -113,7 +110,7 @@ class UploadLocksDB {
|
|||||||
${_trackUploadTable.columnFileKey} TEXT NOT NULL,
|
${_trackUploadTable.columnFileKey} TEXT NOT NULL,
|
||||||
${_trackUploadTable.columnObjectKey} TEXT NOT NULL,
|
${_trackUploadTable.columnObjectKey} TEXT NOT NULL,
|
||||||
${_trackUploadTable.columnCompleteUrl} TEXT NOT NULL,
|
${_trackUploadTable.columnCompleteUrl} TEXT NOT NULL,
|
||||||
${_trackUploadTable.columnCompletionStatus} TEXT NOT NULL,
|
${_trackUploadTable.columnStatus} TEXT DEFAULT '${trackStatus.pending}' NOT NULL,
|
||||||
${_trackUploadTable.columnPartSize} INTEGER NOT NULL
|
${_trackUploadTable.columnPartSize} INTEGER NOT NULL
|
||||||
)
|
)
|
||||||
''',
|
''',
|
||||||
@@ -124,6 +121,7 @@ class UploadLocksDB {
|
|||||||
${_partsTable.columnObjectKey} TEXT NOT NULL REFERENCES ${_trackUploadTable.table}(${_trackUploadTable.columnObjectKey}) ON DELETE CASCADE,
|
${_partsTable.columnObjectKey} TEXT NOT NULL REFERENCES ${_trackUploadTable.table}(${_trackUploadTable.columnObjectKey}) ON DELETE CASCADE,
|
||||||
${_partsTable.columnPartNumber} INTEGER NOT NULL,
|
${_partsTable.columnPartNumber} INTEGER NOT NULL,
|
||||||
${_partsTable.columnPartUrl} TEXT NOT NULL,
|
${_partsTable.columnPartUrl} TEXT NOT NULL,
|
||||||
|
${_partsTable.columnPartETag} TEXT,
|
||||||
${_partsTable.columnPartStatus} TEXT NOT NULL,
|
${_partsTable.columnPartStatus} TEXT NOT NULL,
|
||||||
PRIMARY KEY (${_partsTable.columnObjectKey}, ${_partsTable.columnPartNumber})
|
PRIMARY KEY (${_partsTable.columnObjectKey}, ${_partsTable.columnPartNumber})
|
||||||
)
|
)
|
||||||
@@ -204,7 +202,7 @@ class UploadLocksDB {
|
|||||||
return rows.isNotEmpty;
|
return rows.isNotEmpty;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<MultipartUploadURLs> getCachedLinks(
|
Future<(MultipartUploadURLs, String)> getCachedLinks(
|
||||||
String localId,
|
String localId,
|
||||||
String fileHash,
|
String fileHash,
|
||||||
) async {
|
) async {
|
||||||
@@ -231,12 +229,16 @@ class UploadLocksDB {
|
|||||||
partsStatus.length,
|
partsStatus.length,
|
||||||
(index) => "",
|
(index) => "",
|
||||||
);
|
);
|
||||||
|
final Map<int, String> partETags = {};
|
||||||
|
|
||||||
for (final part in partsStatus) {
|
for (final part in partsStatus) {
|
||||||
final partNumber = part[_partsTable.columnPartNumber] as int;
|
final partNumber = part[_partsTable.columnPartNumber] as int;
|
||||||
final partUrl = part[_partsTable.columnPartUrl] as String;
|
final partUrl = part[_partsTable.columnPartUrl] as String;
|
||||||
final partStatus = part[_partsTable.columnPartStatus] as String;
|
final partStatus = part[_partsTable.columnPartStatus] as String;
|
||||||
partsURLs[partNumber] = partUrl;
|
partsURLs[partNumber] = partUrl;
|
||||||
|
if (part[_partsTable.columnPartETag] != null) {
|
||||||
|
partETags[partNumber] = part[_partsTable.columnPartETag] as String;
|
||||||
|
}
|
||||||
partUploadStatus.add(partStatus == "uploaded");
|
partUploadStatus.add(partStatus == "uploaded");
|
||||||
}
|
}
|
||||||
final urls = MultipartUploadURLs(
|
final urls = MultipartUploadURLs(
|
||||||
@@ -244,9 +246,10 @@ class UploadLocksDB {
|
|||||||
completeURL: row[_trackUploadTable.columnCompleteUrl] as String,
|
completeURL: row[_trackUploadTable.columnCompleteUrl] as String,
|
||||||
partsURLs: partsURLs,
|
partsURLs: partsURLs,
|
||||||
partUploadStatus: partUploadStatus,
|
partUploadStatus: partUploadStatus,
|
||||||
|
partETags: partETags,
|
||||||
);
|
);
|
||||||
|
|
||||||
return urls;
|
return (urls, row[_trackUploadTable.columnStatus] as String);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> createTrackUploadsEntry(
|
Future<void> createTrackUploadsEntry(
|
||||||
@@ -270,7 +273,6 @@ class UploadLocksDB {
|
|||||||
_trackUploadTable.columnEncryptedFilePath: encryptedFilePath,
|
_trackUploadTable.columnEncryptedFilePath: encryptedFilePath,
|
||||||
_trackUploadTable.columnEncryptedFileSize: fileSize,
|
_trackUploadTable.columnEncryptedFileSize: fileSize,
|
||||||
_trackUploadTable.columnFileKey: fileKey,
|
_trackUploadTable.columnFileKey: fileKey,
|
||||||
_trackUploadTable.columnCompletionStatus: _trackStatus.pending,
|
|
||||||
_trackUploadTable.columnPartSize: multipartPartSize,
|
_trackUploadTable.columnPartSize: multipartPartSize,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -289,29 +291,19 @@ class UploadLocksDB {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// print all database entries
|
|
||||||
final trackUploads = await db.query(_trackUploadTable.table);
|
|
||||||
final parts = await db.query(_partsTable.table);
|
|
||||||
print("Track Uploads:");
|
|
||||||
for (final trackUpload in trackUploads) {
|
|
||||||
print(trackUpload);
|
|
||||||
}
|
|
||||||
print("Parts:");
|
|
||||||
for (final part in parts) {
|
|
||||||
print(part);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> updatePartStatus(
|
Future<void> updatePartStatus(
|
||||||
String objectKey,
|
String objectKey,
|
||||||
int partNumber,
|
int partNumber,
|
||||||
|
String etag,
|
||||||
) async {
|
) async {
|
||||||
final db = await instance.database;
|
final db = await instance.database;
|
||||||
await db.update(
|
await db.update(
|
||||||
_partsTable.table,
|
_partsTable.table,
|
||||||
{
|
{
|
||||||
_partsTable.columnPartStatus: _partStatus.uploaded,
|
_partsTable.columnPartStatus: _partStatus.uploaded,
|
||||||
|
_partsTable.columnPartETag: etag,
|
||||||
},
|
},
|
||||||
where:
|
where:
|
||||||
'${_partsTable.columnObjectKey} = ? AND ${_partsTable.columnPartNumber} = ?',
|
'${_partsTable.columnObjectKey} = ? AND ${_partsTable.columnPartNumber} = ?',
|
||||||
@@ -319,17 +311,29 @@ class UploadLocksDB {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> updateCompletionStatus(
|
Future<void> updateTrackUploadStatus(
|
||||||
String objectKey,
|
String objectKey,
|
||||||
|
String status,
|
||||||
) async {
|
) async {
|
||||||
final db = await instance.database;
|
final db = await instance.database;
|
||||||
await db.update(
|
await db.update(
|
||||||
_trackUploadTable.table,
|
_trackUploadTable.table,
|
||||||
{
|
{
|
||||||
_trackUploadTable.columnCompletionStatus: _trackStatus.completed,
|
_trackUploadTable.columnStatus: status,
|
||||||
},
|
},
|
||||||
where: '${_trackUploadTable.columnObjectKey} = ?',
|
where: '${_trackUploadTable.columnObjectKey} = ?',
|
||||||
whereArgs: [objectKey],
|
whereArgs: [objectKey],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<int> deleteCompletedRecord(
|
||||||
|
String localId,
|
||||||
|
) async {
|
||||||
|
final db = await instance.database;
|
||||||
|
return await db.delete(
|
||||||
|
_trackUploadTable.table,
|
||||||
|
where: '${_trackUploadTable.columnLocalID} = ?',
|
||||||
|
whereArgs: [localId],
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -612,6 +612,8 @@ class FileUploader {
|
|||||||
}
|
}
|
||||||
await FilesDB.instance.update(remoteFile);
|
await FilesDB.instance.update(remoteFile);
|
||||||
}
|
}
|
||||||
|
await UploadLocksDB.instance.deleteCompletedRecord(lockKey);
|
||||||
|
|
||||||
if (!_isBackground) {
|
if (!_isBackground) {
|
||||||
Bus.instance.fire(
|
Bus.instance.fire(
|
||||||
LocalPhotosUpdatedEvent(
|
LocalPhotosUpdatedEvent(
|
||||||
|
@@ -13,6 +13,7 @@ import "package:photos/utils/xml_parser_util.dart";
|
|||||||
|
|
||||||
final _enteDio = NetworkClient.instance.enteDio;
|
final _enteDio = NetworkClient.instance.enteDio;
|
||||||
final _dio = NetworkClient.instance.getDio();
|
final _dio = NetworkClient.instance.getDio();
|
||||||
|
final _uploadLocksDb = UploadLocksDB.instance;
|
||||||
|
|
||||||
class PartETag extends XmlParsableObject {
|
class PartETag extends XmlParsableObject {
|
||||||
final int partNumber;
|
final int partNumber;
|
||||||
@@ -37,12 +38,14 @@ class MultipartUploadURLs {
|
|||||||
final List<String> partsURLs;
|
final List<String> partsURLs;
|
||||||
final String completeURL;
|
final String completeURL;
|
||||||
final List<bool>? partUploadStatus;
|
final List<bool>? partUploadStatus;
|
||||||
|
final Map<int, String>? partETags;
|
||||||
|
|
||||||
MultipartUploadURLs({
|
MultipartUploadURLs({
|
||||||
required this.objectKey,
|
required this.objectKey,
|
||||||
required this.partsURLs,
|
required this.partsURLs,
|
||||||
required this.completeURL,
|
required this.completeURL,
|
||||||
this.partUploadStatus,
|
this.partUploadStatus,
|
||||||
|
this.partETags,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory MultipartUploadURLs.fromMap(Map<String, dynamic> map) {
|
factory MultipartUploadURLs.fromMap(Map<String, dynamic> map) {
|
||||||
@@ -83,7 +86,7 @@ Future<void> createTableEntry(
|
|||||||
int fileSize,
|
int fileSize,
|
||||||
Uint8List fileKey,
|
Uint8List fileKey,
|
||||||
) async {
|
) async {
|
||||||
await UploadLocksDB.instance.createTrackUploadsEntry(
|
await _uploadLocksDb.createTrackUploadsEntry(
|
||||||
localId,
|
localId,
|
||||||
fileHash,
|
fileHash,
|
||||||
urls,
|
urls,
|
||||||
@@ -98,13 +101,19 @@ Future<String> putExistingMultipartFile(
|
|||||||
String localId,
|
String localId,
|
||||||
String fileHash,
|
String fileHash,
|
||||||
) async {
|
) async {
|
||||||
final urls = await UploadLocksDB.instance.getCachedLinks(localId, fileHash);
|
final (urls, status) = await _uploadLocksDb.getCachedLinks(localId, fileHash);
|
||||||
|
|
||||||
// upload individual parts and get their etags
|
Map<int, String> etags = urls.partETags ?? {};
|
||||||
final etags = await uploadParts(urls, encryptedFile);
|
|
||||||
|
|
||||||
// complete the multipart upload
|
if (status == UploadLocksDB.trackStatus.pending) {
|
||||||
await completeMultipartUpload(urls.objectKey, etags, urls.completeURL);
|
// upload individual parts and get their etags
|
||||||
|
etags = await uploadParts(urls, encryptedFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != UploadLocksDB.trackStatus.completed) {
|
||||||
|
// complete the multipart upload
|
||||||
|
await completeMultipartUpload(urls.objectKey, etags, urls.completeURL);
|
||||||
|
}
|
||||||
|
|
||||||
return urls.objectKey;
|
return urls.objectKey;
|
||||||
}
|
}
|
||||||
@@ -129,7 +138,7 @@ Future<Map<int, String>> uploadParts(
|
|||||||
final partsURLs = url.partsURLs;
|
final partsURLs = url.partsURLs;
|
||||||
final partUploadStatus = url.partUploadStatus;
|
final partUploadStatus = url.partUploadStatus;
|
||||||
final partsLength = partsURLs.length;
|
final partsLength = partsURLs.length;
|
||||||
final etags = <int, String>{};
|
final etags = url.partETags ?? <int, String>{};
|
||||||
|
|
||||||
for (int i = 0; i < partsLength; i++) {
|
for (int i = 0; i < partsLength; i++) {
|
||||||
if (i < (partUploadStatus?.length ?? 0) &&
|
if (i < (partUploadStatus?.length ?? 0) &&
|
||||||
@@ -163,8 +172,12 @@ Future<Map<int, String>> uploadParts(
|
|||||||
|
|
||||||
etags[i] = eTag!;
|
etags[i] = eTag!;
|
||||||
|
|
||||||
await UploadLocksDB.instance.updatePartStatus(url.objectKey, i);
|
await _uploadLocksDb.updatePartStatus(url.objectKey, i, eTag);
|
||||||
}
|
}
|
||||||
|
await _uploadLocksDb.updateTrackUploadStatus(
|
||||||
|
url.objectKey,
|
||||||
|
UploadLocksDB.trackStatus.uploaded,
|
||||||
|
);
|
||||||
|
|
||||||
return etags;
|
return etags;
|
||||||
}
|
}
|
||||||
@@ -193,7 +206,10 @@ Future<void> completeMultipartUpload(
|
|||||||
contentType: "text/xml",
|
contentType: "text/xml",
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
await UploadLocksDB.instance.updateCompletionStatus(objectKey);
|
await _uploadLocksDb.updateTrackUploadStatus(
|
||||||
|
objectKey,
|
||||||
|
UploadLocksDB.trackStatus.completed,
|
||||||
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Logger("MultipartUpload").severe(e);
|
Logger("MultipartUpload").severe(e);
|
||||||
rethrow;
|
rethrow;
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
// ignore_for_file: implementation_imports
|
// ignore_for_file: implementation_imports
|
||||||
|
|
||||||
import "package:xml/src/xml/entities/named_entities.dart";
|
|
||||||
import "package:xml/xml.dart";
|
import "package:xml/xml.dart";
|
||||||
|
|
||||||
// used for classes that can be converted to xml
|
// used for classes that can be converted to xml
|
||||||
@@ -16,7 +15,6 @@ String convertJs2Xml(Map<String, dynamic> json) {
|
|||||||
return builder.buildDocument().toXmlString(
|
return builder.buildDocument().toXmlString(
|
||||||
pretty: true,
|
pretty: true,
|
||||||
indent: ' ',
|
indent: ' ',
|
||||||
entityMapping: defaultMyEntityMapping,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,6 +36,6 @@ void buildXml(XmlBuilder builder, dynamic node) {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
builder.text(node.toString());
|
builder.text(node is String ? node : node.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user