Skip to content

Commit

Permalink
android upload duration logic
Browse files Browse the repository at this point in the history
  • Loading branch information
parveshneedhoo committed Aug 22, 2024
1 parent 8fb2cf8 commit ea35dc4
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 10 deletions.
17 changes: 15 additions & 2 deletions src/android/AckDatabase.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,35 @@

import android.content.Context;

import androidx.annotation.NonNull;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import androidx.room.TypeConverters;
import androidx.room.migration.Migration;
import androidx.sqlite.db.SupportSQLiteDatabase;
import androidx.work.Data;

@Database(entities = {UploadEvent.class}, version = 5)
@Database(entities = {UploadEvent.class}, version = 6)
@TypeConverters(value = {Data.class})
public abstract class AckDatabase extends RoomDatabase {
private static AckDatabase instance;

public static AckDatabase getInstance(final Context context) {
static final Migration MIGRATION_5_6 = new Migration(5, 6) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE upload_events ADD COLUMN start_upload_time INTEGER NOT NULL DEFAULT 0");
database.execSQL("ALTER TABLE upload_events ADD COLUMN finish_upload_time INTEGER NOT NULL DEFAULT 0");
}
};


public static synchronized AckDatabase getInstance(final Context context) {
if (instance == null) {
instance = Room
.databaseBuilder(context, AckDatabase.class, "cordova-plugin-background-upload.db")
.fallbackToDestructiveMigration()
.addMigrations(MIGRATION_5_6)
.build();
}
return instance;
Expand Down
15 changes: 10 additions & 5 deletions src/android/FileTransferBackground.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
Expand Down Expand Up @@ -81,7 +82,7 @@ private void sendProgress(final String id, int progressPercent) {
}
}

private void sendSuccess(final String id, final String response, int statusCode) {
private void sendSuccess(final String id, final String response, int statusCode, long uploadDuration, long finishUploadTime) {
if (response != null && !response.isEmpty()) {
logMessage("eventLabel='Uploader onSuccess' uploadId='" + id + "' response='" + response.substring(0, Math.min(2000, response.length() - 1)) + "'");
} else {
Expand All @@ -95,6 +96,8 @@ private void sendSuccess(final String id, final String response, int statusCode)
.put("state", "UPLOADED")
.put("serverResponse", response)
.put("statusCode", statusCode)
.put("uploadDuration", uploadDuration)
.put("finishUploadTime", finishUploadTime)
);
} catch (JSONException e) {
// Can't really happen but just in case
Expand Down Expand Up @@ -193,7 +196,7 @@ private void initManager(String options, final CallbackContext callbackContext)
int ackDelay = 0;
for (UploadEvent ack : uploadEvents) {
executorService.schedule(() -> {
handleAck(ack.getOutputData());
handleAck(ack.getOutputData(), ack.calculateUploadDuration(), ack.getFinishUploadTime());
}, ackDelay, TimeUnit.MILLISECONDS);
ackDelay += 200;
}
Expand Down Expand Up @@ -227,7 +230,7 @@ private void initManager(String options, final CallbackContext callbackContext)
// The corresponding ACK is already in the DB, if it not, the task is just a leftover
String id = info.getOutputData().getString(UploadTask.KEY_OUTPUT_ID);
if (ackDatabase.uploadEventDao().exists(id)) {
handleAck(info.getOutputData());
handleAck(info.getOutputData(), ackDatabase.uploadEventDao().getById(id).calculateUploadDuration(), ackDatabase.uploadEventDao().getById(id).getFinishUploadTime());
}
}, 0, TimeUnit.MILLISECONDS);
break;
Expand Down Expand Up @@ -400,7 +403,7 @@ private void acknowledgeEvent(String eventId, CallbackContext context) {
/**
* Handle ACK data and send it to the JS.
*/
private void handleAck(final Data ackData) {
private void handleAck(final Data ackData, final long uploadDuration, final long finishUploadTime) {
// If upload was successful
if (!ackData.getBoolean(UploadTask.KEY_OUTPUT_IS_ERROR, false)) {
// Read response from file if present
Expand All @@ -412,7 +415,9 @@ private void handleAck(final Data ackData) {
sendSuccess(
ackData.getString(UploadTask.KEY_OUTPUT_ID),
response,
ackData.getInt(UploadTask.KEY_OUTPUT_STATUS_CODE, -1 /* If this is sent, something is really wrong */)
ackData.getInt(UploadTask.KEY_OUTPUT_STATUS_CODE, -1 /* If this is sent, something is really wrong */),
uploadDuration,
finishUploadTime
);

} else {
Expand Down
24 changes: 23 additions & 1 deletion src/android/UploadEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,19 @@ public class UploadEvent {
@NonNull
private Data outputData;

public UploadEvent(@NonNull final String id, @NonNull final Data outputData) {
@ColumnInfo(name = "start_upload_time")
@NonNull
private long startUploadTime;

@ColumnInfo(name = "finish_upload_time")
@NonNull
private long finishUploadTime;

public UploadEvent(@NonNull final String id, @NonNull final Data outputData, @NonNull final long startUploadTime, @NonNull final long finishUploadTime) {
this.id = id;
this.outputData = outputData;
this.startUploadTime = startUploadTime;
this.finishUploadTime = finishUploadTime;
}

@NonNull
Expand All @@ -30,4 +40,16 @@ public String getId() {
public Data getOutputData() {
return outputData;
}

public long getStartUploadTime() {
return startUploadTime;
}

public long getFinishUploadTime() {
return finishUploadTime;
}

public long calculateUploadDuration() {
return finishUploadTime - startUploadTime;
}
}
8 changes: 6 additions & 2 deletions src/android/UploadTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ public void release() { }
private static int concurrency = 1;
private static Semaphore concurrentUploads = new Semaphore(concurrency, true);
private static Mutex concurrencyLock = new Mutex();
long startTime = 0;
long endTime = 0;

public UploadTask(@NonNull Context context, @NonNull WorkerParameters workerParams) {

Expand Down Expand Up @@ -189,6 +191,7 @@ public Result doWork() {
return Result.retry();
}

startTime = System.currentTimeMillis();
// Register me
uploadForegroundNotification.progress(getId(), 0f);
handleNotification();
Expand Down Expand Up @@ -237,7 +240,7 @@ public Result doWork() {
.putString(KEY_OUTPUT_FAILURE_REASON, "User cancelled")
.putBoolean(KEY_OUTPUT_FAILURE_CANCELED, true)
.build();
AckDatabase.getInstance(getApplicationContext()).uploadEventDao().insert(new UploadEvent(id, data));
AckDatabase.getInstance(getApplicationContext()).uploadEventDao().insert(new UploadEvent(id, data, startTime, endTime));
return Result.success(data);
} else {
// But if it was not it must be a connectivity problem or
Expand All @@ -246,6 +249,7 @@ public Result doWork() {
return Result.retry();
}
} finally {
endTime = System.currentTimeMillis();
// Always remove ourselves from the notification
uploadForegroundNotification.done(getId());
}
Expand Down Expand Up @@ -281,7 +285,7 @@ public Result doWork() {
}

final Data data = outputData.build();
AckDatabase.getInstance(getApplicationContext()).uploadEventDao().insert(new UploadEvent(id, data));
AckDatabase.getInstance(getApplicationContext()).uploadEventDao().insert(new UploadEvent(id, data, startTime, endTime));
return Result.success(data);
}

Expand Down

0 comments on commit ea35dc4

Please sign in to comment.