From 02b8fab56a0dbf584624e7b2a24ee21289ad7c3d Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 23 May 2025 06:49:47 +0000 Subject: [PATCH] Refactor: Replace native SQLite with WatermelonDB This commit removes the native SQLite dependency for job queuing on both Android and iOS platforms and replaces it with WatermelonDB. Key changes include: - Added WatermelonDB and its dependencies. - Defined a WatermelonDB schema for jobs. - Implemented a new `WatermelonDBJobStore` that uses WatermelonDB for all database operations (add, get, update, delete jobs). - Updated `src/Queue.ts` to use the new `WatermelonDBJobStore`, making its methods asynchronous where necessary. - Removed all native Java code related to SQLite and Room from the `android` directory. - Removed all native Swift and Objective-C code related to SQLite from the `ios` directory. - Updated Android build files (`build.gradle`) to remove Room dependencies. - Updated iOS project files (`project.pbxproj`, `.podspec`) to remove references to native source files and SQLite dependencies. This change moves all database logic to the JavaScript side, simplifying the native layer and leveraging WatermelonDB for cross-platform data persistence. --- android/build.gradle | 3 - .../com.github.simonerm.JobDatabase/1.json | 88 ----- .../com/github/simonerm/ConversionHelper.java | 62 ---- .../main/java/com/github/simonerm/Job.java | 135 ------- .../main/java/com/github/simonerm/JobDao.java | 57 --- .../java/com/github/simonerm/JobDatabase.java | 51 --- .../com/github/simonerm/JobQueueModule.java | 137 ------- .../com/github/simonerm/JobQueuePackage.java | 23 -- babel.config.js | 5 +- ios/Job.swift | 339 ------------------ ios/JobQueue-Bridging-Header.h | 1 - ios/JobQueue.h | 5 - ios/JobQueue.m | 18 - ios/JobQueue.swift | 199 ---------- ios/JobQueue.xcodeproj/project.pbxproj | 22 -- ios/SQLTable.swift | 3 - ios/SQLiteDatabase.swift | 68 ---- lib/commonjs/Queue.js | 2 +- lib/commonjs/Queue.js.map | 2 +- lib/module/Queue.js | 2 +- lib/module/Queue.js.map | 2 +- package.json | 4 +- react-native-job-queue.podspec | 5 +- src/JobStore.ts | 217 +++++++++++ src/Queue.ts | 64 ++-- src/watermelon/database.ts | 47 +++ src/watermelon/schema.ts | 24 ++ yarn.lock | 201 ++++++++++- 28 files changed, 535 insertions(+), 1251 deletions(-) delete mode 100644 android/schemas/com.github.simonerm.JobDatabase/1.json delete mode 100644 android/src/main/java/com/github/simonerm/ConversionHelper.java delete mode 100644 android/src/main/java/com/github/simonerm/Job.java delete mode 100644 android/src/main/java/com/github/simonerm/JobDao.java delete mode 100644 android/src/main/java/com/github/simonerm/JobDatabase.java delete mode 100644 android/src/main/java/com/github/simonerm/JobQueueModule.java delete mode 100644 android/src/main/java/com/github/simonerm/JobQueuePackage.java delete mode 100644 ios/Job.swift delete mode 100644 ios/JobQueue-Bridging-Header.h delete mode 100644 ios/JobQueue.h delete mode 100644 ios/JobQueue.m delete mode 100644 ios/JobQueue.swift delete mode 100644 ios/SQLTable.swift delete mode 100644 ios/SQLiteDatabase.swift create mode 100644 src/JobStore.ts create mode 100644 src/watermelon/database.ts create mode 100644 src/watermelon/schema.ts diff --git a/android/build.gradle b/android/build.gradle index 4378548..3b6a569 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -65,7 +65,4 @@ repositories { dependencies { //noinspection GradleDynamicVersion api 'com.facebook.react:react-native:+' - implementation "androidx.room:room-runtime:2.5.2" - annotationProcessor "androidx.room:room-compiler:2.5.2" - implementation "androidx.room:room-ktx:2.5.2" } diff --git a/android/schemas/com.github.simonerm.JobDatabase/1.json b/android/schemas/com.github.simonerm.JobDatabase/1.json deleted file mode 100644 index b28cbd3..0000000 --- a/android/schemas/com.github.simonerm.JobDatabase/1.json +++ /dev/null @@ -1,88 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 1, - "identityHash": "e0e3e2eb03357230350c15ce572617a7", - "entities": [ - { - "tableName": "job", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `worker_name` TEXT, `active` INTEGER NOT NULL, `payload` TEXT, `attempts` INTEGER NOT NULL, `created` TEXT, `success` INTEGER NOT NULL, `completed` INTEGER NOT NULL, `is_deleted` INTEGER NOT NULL DEFAULT 0, `created` TEXT, PRIMARY KEY(`id`))", - "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "workerName", - "columnName": "worker_name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "active", - "columnName": "active", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "payload", - "columnName": "payload", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "attempts", - "columnName": "attempts", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "created", - "columnName": "created", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "success", - "columnName": "success", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "completed", - "columnName": "completed", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "isDeleted", - "columnName": "is_deleted", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - }, - { - "fieldPath": "status", - "columnName": "status", - "affinity": "TEXT", - "notNull": false - } - ], - "primaryKey": { - "columnNames": [ - "id" - ], - "autoGenerate": false - }, - "indices": [], - "foreignKeys": [] - } - ], - "setupQueries": [ - "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", - "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"e0e3e2eb03357230350c15ce572617a7\")" - ] - } -} \ No newline at end of file diff --git a/android/src/main/java/com/github/simonerm/ConversionHelper.java b/android/src/main/java/com/github/simonerm/ConversionHelper.java deleted file mode 100644 index 0f43620..0000000 --- a/android/src/main/java/com/github/simonerm/ConversionHelper.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.github.simonerm; - -import android.os.Bundle; - -import com.facebook.react.bridge.Arguments; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.bridge.WritableArray; -import com.facebook.react.bridge.WritableMap; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -public class ConversionHelper { - - public static WritableMap getJobAsWritableMap(Job job){ - - return Arguments.fromBundle(getJobAsBundle(job)); - } - public static WritableArray getJobsAsWritableArray(List jobs){ - List jobsAsBundleList =new ArrayList<>(); - Iterator jobIterable=jobs.iterator(); - while(jobIterable.hasNext()){ - Job job =jobIterable.next(); - jobsAsBundleList.add(getJobAsBundle(job)); - } - - return Arguments.fromArray(jobsAsBundleList.toArray(new Bundle[jobsAsBundleList.size()])); - } - public static Job getJobFromReadableMap(ReadableMap jobAsMap){ - Job job = new Job(); - job.setId(jobAsMap.getString("id")); - job.setWorkerName(jobAsMap.getString("workerName")); - job.setActive(jobAsMap.getInt("active")); - job.setPayload(jobAsMap.getString("payload")); - job.setAttempts(jobAsMap.getInt("attempts")); - job.setMetaData(jobAsMap.getString("metaData")); - job.setTimeout(jobAsMap.getInt("timeout")); - job.setPriority(jobAsMap.getInt("priority")); - job.setCreated(jobAsMap.getString("created")); - job.setFailed(jobAsMap.getString("failed")); - job.setIsDeleted(jobAsMap.hasKey("isDeleted") && jobAsMap.getBoolean("isDeleted")); - job.setStatus(jobAsMap.getString("status")); - return job; - } - private static Bundle getJobAsBundle(Job job){ - Bundle jobAsBundle =new Bundle(); - jobAsBundle.putString("id",job.getId()); - jobAsBundle.putString("workerName",job.getWorkerName()); - jobAsBundle.putInt("active",job.getActive()); - jobAsBundle.putString("payload",job.getPayload()); - jobAsBundle.putString("metaData",job.getMetaData()); - jobAsBundle.putInt("attempts",job.getAttempts()); - jobAsBundle.putInt("timeout",job.getTimeout()); - jobAsBundle.putInt("priority",job.getPriority()); - jobAsBundle.putString("created",job.getCreated()); - jobAsBundle.putString("failed",job.getFailed()); - jobAsBundle.putBoolean("isDeleted", job.isDeleted()); - jobAsBundle.putString("status",job.getStatus()); - return jobAsBundle; - } -} diff --git a/android/src/main/java/com/github/simonerm/Job.java b/android/src/main/java/com/github/simonerm/Job.java deleted file mode 100644 index 6ff368b..0000000 --- a/android/src/main/java/com/github/simonerm/Job.java +++ /dev/null @@ -1,135 +0,0 @@ -package com.github.simonerm; - -import androidx.annotation.NonNull; -import androidx.room.ColumnInfo; -import androidx.room.Entity; -import androidx.room.PrimaryKey; - -import java.sql.Date; - -@Entity(tableName = "job") -public class Job { - @NonNull - @PrimaryKey - private String id; - - @ColumnInfo(name = "worker_name") - private String workerName; - - private int active; - - private String payload; - - @ColumnInfo(name = "meta_data") - private String metaData; - - private int attempts; - - private String created; - - private int timeout; - - private int priority; - - private String failed; - - private String status; - - @ColumnInfo(name = "is_deleted") - private boolean isDeleted; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getWorkerName() { - return workerName; - } - - public void setWorkerName(String workerName) { - this.workerName = workerName; - } - - public int getActive() { - return active; - } - - public void setActive(int active) { - this.active = active; - } - - public String getPayload() { - return payload; - } - - public void setPayload(String payload) { - this.payload = payload; - } - - public int getAttempts() { - return attempts; - } - - public void setAttempts(int attempts) { - this.attempts = attempts; - } - - public String getCreated() { - return created; - } - - public void setCreated(String created) { - this.created = created; - } - - public int getTimeout() { - return timeout; - } - - public void setTimeout(int timeout) { - this.timeout = timeout; - } - - public String getFailed() { - return failed; - } - - public void setFailed(String failed) { - this.failed = failed; - } - - public int getPriority() { - return priority; - } - - public void setPriority(int priority) { - this.priority = priority; - } - - public String getMetaData() { - return metaData; - } - - public void setMetaData(String metaData) { - this.metaData = metaData; - } - public boolean isDeleted() { - return isDeleted; - } - - public void setIsDeleted(boolean isDeleted) { - this.isDeleted = isDeleted; - } - - public String getStatus() { - return status; - } - - public void setStatus(String status) { - this.status = status; - } -} \ No newline at end of file diff --git a/android/src/main/java/com/github/simonerm/JobDao.java b/android/src/main/java/com/github/simonerm/JobDao.java deleted file mode 100644 index 15c3882..0000000 --- a/android/src/main/java/com/github/simonerm/JobDao.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.github.simonerm; - -import androidx.room.Dao; -import androidx.room.Delete; -import androidx.room.Insert; -import androidx.room.Query; -import androidx.room.Update; - -import java.util.List; - -@Dao -public interface JobDao { - @Query("SELECT * FROM job WHERE is_deleted == 0") - List getAll(); - - @Query("SELECT * FROM job WHERE active == 0 AND status != 'failed' AND status != 'cancelled' AND is_deleted == 0 ORDER BY priority DESC,datetime(created) LIMIT 1") - Job getNextJob(); - - @Query("SELECT * FROM job WHERE active == 0 AND status == 'processing' AND is_deleted = 0 ORDER BY priority DESC,datetime(created) LIMIT 1") - Job getWorkInProgressJob(); - - @Query("SELECT * FROM job WHERE is_deleted == 0 ORDER BY priority DESC,datetime(created)") - List getJobs(); - - @Query("SELECT * FROM job ORDER BY priority DESC,datetime(created)") - List getJobsWithDeleted(); - - @Query("SELECT * FROM job WHERE active == 1 AND is_deleted == 0") - List getActiveMarkedJobs(); - - @Query("SELECT * FROM job WHERE active == 0 AND status != 'failed' AND status != 'cancelled' AND worker_name == :workerName AND is_deleted == 0 ORDER BY priority DESC,datetime(created) LIMIT :limit") - List getJobsForWorker(String workerName, int limit); - - @Query("SELECT * FROM job WHERE active == 0 AND status != 'failed' AND status != 'cancelled' AND worker_name == :workerName ORDER BY priority DESC,datetime(created) LIMIT :limit") - List getJobsForWorkerWithDeleted(String workerName, int limit); - - @Query("SELECT * FROM job WHERE id LIKE :id AND is_deleted == 0") - Job findById(String id); - - @Query("SELECT COUNT(*) from job WHERE is_deleted == 0") - int countJobs(); - - @Update - void update(Job job); - - @Insert - void insert(Job job); - - @Delete - void delete(Job job); - - @Query("UPDATE job SET is_deleted = 1 WHERE worker_name == :workerName") - void markJobsAsDeletedByWorkerName(String workerName); - - @Query("UPDATE job SET is_deleted = 1 WHERE id = :jobId") - void softDeleteJob(String jobId); -} diff --git a/android/src/main/java/com/github/simonerm/JobDatabase.java b/android/src/main/java/com/github/simonerm/JobDatabase.java deleted file mode 100644 index 94d46b5..0000000 --- a/android/src/main/java/com/github/simonerm/JobDatabase.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.github.simonerm; - -import android.content.Context; - -import androidx.room.Database; -import androidx.room.Room; -import androidx.room.RoomDatabase; -import androidx.room.migration.Migration; -import androidx.sqlite.db.SupportSQLiteDatabase; - -@Database(entities = {Job.class}, version = 2) -public abstract class JobDatabase extends RoomDatabase { - - private static JobDatabase INSTANCE; - - public abstract JobDao jobDao(); - - public static JobDatabase getAppDatabase(Context context) { - if (INSTANCE == null) { - INSTANCE = - Room.databaseBuilder(context.getApplicationContext(), JobDatabase.class, "job-database") - .addMigrations(MIGRATION_1_2) - .build(); - } - return INSTANCE; - } - - public static void destroyInstance() { - INSTANCE = null; - } - - static final Migration MIGRATION_1_2 = new Migration(1, 2) { - @Override - public void migrate(SupportSQLiteDatabase database) { - database.execSQL("CREATE TABLE IF NOT EXISTS job(" + - "id CHAR(36) PRIMARY KEY NOT NULL," + - "worker_name CHAR(255) NOT NULL," + - "active INTEGER NOT NULL," + - "payload CHAR(1024)," + - "meta_data CHAR(1024)," + - "attempts INTEGER NOT NULL," + - "created CHAR(255)," + - "failed CHAR(255)," + - "timeout INTEGER NOT NULL," + - "priority Integer NOT NULL," + - "is_deleted INTEGER NOT NULL DEFAULT 0," + - "status CHAR(255)" + - ")"); // Removed the extra semicolon and parenthesis - } - }; -} \ No newline at end of file diff --git a/android/src/main/java/com/github/simonerm/JobQueueModule.java b/android/src/main/java/com/github/simonerm/JobQueueModule.java deleted file mode 100644 index d4c685c..0000000 --- a/android/src/main/java/com/github/simonerm/JobQueueModule.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.github.simonerm; - -import com.facebook.react.bridge.Arguments; -import com.facebook.react.bridge.Promise; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.Callback; -import com.facebook.react.bridge.ReadableMap; - -import java.util.Iterator; -import java.util.List; - -public class JobQueueModule extends ReactContextBaseJavaModule { - - private final ReactApplicationContext reactContext; - - public JobQueueModule(ReactApplicationContext reactContext) { - super(reactContext); - this.reactContext = reactContext; - } - - @Override - public String getName() { - return "JobQueue"; - } - - @ReactMethod - public void addJob(ReadableMap job) { - JobDao dao = JobDatabase.getAppDatabase(this.reactContext).jobDao(); - dao.insert(ConversionHelper.getJobFromReadableMap(job)); - } - - @ReactMethod - public void updateJob(ReadableMap job) { - JobDao dao = JobDatabase.getAppDatabase(this.reactContext).jobDao(); - dao.update(ConversionHelper.getJobFromReadableMap(job)); - } - - @ReactMethod - public void removeJob(ReadableMap job) { - JobDao dao = JobDatabase.getAppDatabase(this.reactContext).jobDao(); - dao.softDeleteJob(ConversionHelper.getJobFromReadableMap(job).getId()); - } - - @ReactMethod - public void removeJobPermanently(ReadableMap job) { - JobDao dao = JobDatabase.getAppDatabase(this.reactContext).jobDao(); - dao.delete(ConversionHelper.getJobFromReadableMap(job)); - } - - @ReactMethod - public void removeJobsByWorkerName(String workerName) { - JobDao dao = JobDatabase.getAppDatabase(this.reactContext).jobDao(); - dao.markJobsAsDeletedByWorkerName(workerName); - } - - @ReactMethod - public void getJobById(String id, Promise promise) { - JobDao dao = JobDatabase.getAppDatabase(this.reactContext).jobDao(); - Job job = dao.findById(id); - promise.resolve(ConversionHelper.getJobAsWritableMap(job)); - } - - @ReactMethod - public void getJobs(Promise promise) { - JobDao dao = JobDatabase.getAppDatabase(this.reactContext).jobDao(); - - List jobs=dao.getJobs(); - promise.resolve(ConversionHelper.getJobsAsWritableArray(jobs)); - } - @ReactMethod - public void getJobsWithDeleted(Promise promise) { - JobDao dao = JobDatabase.getAppDatabase(this.reactContext).jobDao(); - - List jobs=dao.getJobsWithDeleted(); - promise.resolve(ConversionHelper.getJobsAsWritableArray(jobs)); - } - - @ReactMethod - public void getActiveMarkedJobs(Promise promise) { - JobDao dao = JobDatabase.getAppDatabase(this.reactContext).jobDao(); - - List jobs=dao.getActiveMarkedJobs(); - promise.resolve(ConversionHelper.getJobsAsWritableArray(jobs)); - } - - @ReactMethod - public void getJobsForWorker(String workerName,int limit,Promise promise){ - JobDao dao = JobDatabase.getAppDatabase(this.reactContext).jobDao(); - - List jobsToExecute=dao.getJobsForWorker(workerName,limit); - IteratorjobIterator=jobsToExecute.iterator(); - while(jobIterator.hasNext()){ - Job job = jobIterator.next(); - job.setActive(1); - dao.update(job); - } - promise.resolve(ConversionHelper.getJobsAsWritableArray(jobsToExecute)); - } - @ReactMethod - public void getJobsForWorkerWithDeleted(String workerName,int limit,Promise promise){ - JobDao dao = JobDatabase.getAppDatabase(this.reactContext).jobDao(); - - List jobsToExecute=dao.getJobsForWorkerWithDeleted(workerName,limit); - IteratorjobIterator=jobsToExecute.iterator(); - while(jobIterator.hasNext()){ - Job job = jobIterator.next(); - job.setActive(1); - dao.update(job); - } - promise.resolve(ConversionHelper.getJobsAsWritableArray(jobsToExecute)); - } - @ReactMethod - public void getNextJob(Promise promise) { - JobDao dao = JobDatabase.getAppDatabase(this.reactContext).jobDao(); - - Job nextJob=dao.getNextJob(); - if(nextJob!=null){ - promise.resolve(ConversionHelper.getJobAsWritableMap(nextJob)); - }else{ - promise.resolve(Arguments.createMap()); - } - } - @ReactMethod - public void getWorkInProgressJob(Promise promise) { - JobDao dao = JobDatabase.getAppDatabase(this.reactContext).jobDao(); - - Job nextJob=dao.getWorkInProgressJob(); - if(nextJob!=null){ - promise.resolve(ConversionHelper.getJobAsWritableMap(nextJob)); - }else{ - promise.resolve(Arguments.createMap()); - } - } - -} diff --git a/android/src/main/java/com/github/simonerm/JobQueuePackage.java b/android/src/main/java/com/github/simonerm/JobQueuePackage.java deleted file mode 100644 index 9f39913..0000000 --- a/android/src/main/java/com/github/simonerm/JobQueuePackage.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.github.simonerm; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import com.facebook.react.ReactPackage; -import com.facebook.react.bridge.NativeModule; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.uimanager.ViewManager; -import com.facebook.react.bridge.JavaScriptModule; - -public class JobQueuePackage implements ReactPackage { - @Override - public List createNativeModules(ReactApplicationContext reactContext) { - return Arrays.asList(new JobQueueModule(reactContext)); - } - - @Override - public List createViewManagers(ReactApplicationContext reactContext) { - return Collections.emptyList(); - } -} diff --git a/babel.config.js b/babel.config.js index c50a8a0..0c20fc6 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,3 +1,6 @@ module.exports = { - presets: ['module:metro-react-native-babel-preset'] + presets: ['module:metro-react-native-babel-preset'], + plugins: [ + ['@babel/plugin-proposal-decorators', { 'legacy': true }] + ] }; diff --git a/ios/Job.swift b/ios/Job.swift deleted file mode 100644 index cfbee96..0000000 --- a/ios/Job.swift +++ /dev/null @@ -1,339 +0,0 @@ -import Foundation -import SQLite3 - -struct Job { - var id: NSString - var workerName: NSString - var active:Int32 - var payload: NSString - var metaData: NSString - var attempts: Int32 - var created: NSString - var failed: NSString - var timeout: Int32 - var priority: Int32 - var isDeleted: Int32 - var status: NSString -} -extension Job: SQLTable { - static var createStatement: String { - return """ - CREATE TABLE IF NOT EXISTS Job( - id CHAR(36) PRIMARY KEY NOT NULL, - worker_name CHAR(255) NOT NULL, - active INTEGER NOT NULL, - payload CHAR(1024), - meta_data CHAR(1024), - attempts INTEGER NOT NULL, - created CHAR(255), - failed CHAR(255), - timeout INTEGER NOT NULL, - priority Integer NOT NULL, - is_deleted INTEGER NOT NULL DEFAULT 0, - status CHAR(255) - ); - """ - } - static func createJobFromDictionary(job:[String:Any])->Job{ - return Job(id:job["id"] as! NSString, - workerName: job["workerName"] as! NSString, - active:job["active"] as! Int32, - payload:job["payload"] as! NSString, - metaData: job["metaData"] as! NSString, - attempts: job["attempts"] as! Int32, - created: job["created"] as! NSString, - failed: job["failed"] as! NSString, - timeout: job["timeout"] as! Int32, - priority: job["priority"] as! Int32, - isDeleted: job["isDeleted"] as! Int32, - status: job["status"] as! NSString) - } - func toDictionary()->[String:Any]{ - var jobAsDictionary=[String:Any]() - jobAsDictionary["id"]=self.id - jobAsDictionary["workerName"]=self.workerName - jobAsDictionary["active"]=self.active - jobAsDictionary["payload"]=self.payload - jobAsDictionary["metaData"]=self.metaData - jobAsDictionary["attempts"]=self.attempts - jobAsDictionary["created"]=self.created - jobAsDictionary["failed"]=self.failed - jobAsDictionary["timeout"]=self.timeout - jobAsDictionary["priority"]=self.priority - jobAsDictionary["isDeleted"]=self.isDeleted - jobAsDictionary["status"]=self.status - return jobAsDictionary; - } -} -extension SQLiteDatabase { - func add(job: Job) throws { - let insertSql = "INSERT INTO job (id, worker_name, active, payload, meta_data, attempts, created, failed, timeout, priority, is_deleted, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);" - let insertStatement = try prepareStatement(sql: insertSql) - defer { - sqlite3_finalize(insertStatement) - } - - guard (sqlite3_bind_text(insertStatement, 1, job.id.utf8String,-1,nil) == SQLITE_OK && - sqlite3_bind_text(insertStatement, 2, job.workerName.utf8String, -1, nil) == SQLITE_OK && - sqlite3_bind_int(insertStatement, 3, job.active) == SQLITE_OK && - sqlite3_bind_text(insertStatement, 4, job.payload.utf8String, -1, nil) == SQLITE_OK && - sqlite3_bind_text(insertStatement, 5, job.metaData.utf8String, -1, nil) == SQLITE_OK && - sqlite3_bind_int(insertStatement, 6, job.attempts) == SQLITE_OK && - sqlite3_bind_text(insertStatement, 7, job.created.utf8String, -1, nil) == SQLITE_OK && - sqlite3_bind_text(insertStatement, 8, job.failed.utf8String, -1, nil) == SQLITE_OK && - sqlite3_bind_int(insertStatement, 9, job.timeout) == SQLITE_OK && - sqlite3_bind_int(insertStatement, 10, job.priority) == SQLITE_OK && - sqlite3_bind_int(insertStatement, 11, job.isDeleted) == SQLITE_OK && - sqlite3_bind_text(insertStatement, 12, job.status.utf8String, -1, nil) == SQLITE_OK - - )else { - throw SQLiteError.Bind(message: errorMessage) - } - - guard sqlite3_step(insertStatement) == SQLITE_DONE else { - throw SQLiteError.Step(message: errorMessage) - } - } - func getJobBy(id: NSString) -> Job? { - let querySql = "SELECT * FROM job WHERE id = ? AND is_deleted = 0;" - guard let queryStatement = try? prepareStatement(sql: querySql) else { - return nil - } - - defer { - sqlite3_finalize(queryStatement) - } - - guard sqlite3_bind_text(queryStatement, 1, id.utf8String,-1,nil) == SQLITE_OK - else { - return nil - } - - guard sqlite3_step(queryStatement) == SQLITE_ROW else { - return nil - } - - return mapColumnsToJob(sqlStatement: queryStatement) - } - func getNextJob() -> Job? { - let querySql = "SELECT * FROM job WHERE active == 0 AND status != 'failed' AND status != 'cancelled' AND is_deleted = 0 ORDER BY priority DESC,datetime(created) LIMIT 1;" - guard let queryStatement = try? prepareStatement(sql: querySql) else { - return nil - } - - defer { - sqlite3_finalize(queryStatement) - } - - guard sqlite3_step(queryStatement) == SQLITE_ROW else { - return nil - } - - return mapColumnsToJob(sqlStatement: queryStatement) - } - func getWorkInProgressJob() -> Job? { - let querySql = "SELECT * FROM job WHERE active == 0 AND status == 'processing' AND is_deleted = 0 ORDER BY priority DESC,datetime(created) LIMIT 1;" - guard let queryStatement = try? prepareStatement(sql: querySql) else { - return nil - } - - defer { - sqlite3_finalize(queryStatement) - } - - guard sqlite3_step(queryStatement) == SQLITE_ROW else { - return nil - } - - return mapColumnsToJob(sqlStatement: queryStatement) - } - func getJobsForWorker(name:NSString,count:Int32) -> [Job]? { - let querySql = "SELECT * FROM job WHERE active == 0 AND status != 'failed' AND status != 'cancelled' AND worker_name == ? AND is_deleted = 0 ORDER BY priority DESC,datetime(created) LIMIT ?;" - guard let queryStatement = try? prepareStatement(sql: querySql) else { - return nil - } - defer { - sqlite3_finalize(queryStatement) - } - - guard (sqlite3_bind_text(queryStatement, 1, name.utf8String,-1,nil) == SQLITE_OK && - sqlite3_bind_int(queryStatement, 2, count) == SQLITE_OK)else { - return nil - } - - var jobs = [Job]() - while(sqlite3_step(queryStatement) == SQLITE_ROW){ - if let job=mapColumnsToJob(sqlStatement: queryStatement){ - jobs.append(job) - } - } - - return jobs - } - func getJobsForWorkerWithDeleted(name:NSString,count:Int32) -> [Job]? { - let querySql = "SELECT * FROM job WHERE active == 0 AND worker_name == ? ORDER BY priority DESC,datetime(created) LIMIT ?;" - guard let queryStatement = try? prepareStatement(sql: querySql) else { - return nil - } - defer { - sqlite3_finalize(queryStatement) - } - - guard (sqlite3_bind_text(queryStatement, 1, name.utf8String,-1,nil) == SQLITE_OK && - sqlite3_bind_int(queryStatement, 2, count) == SQLITE_OK)else { - return nil - } - - var jobs = [Job]() - while(sqlite3_step(queryStatement) == SQLITE_ROW){ - if let job=mapColumnsToJob(sqlStatement: queryStatement){ - jobs.append(job) - } - } - - return jobs - } - func getJobs() -> [Job]? { - let querySql = "SELECT * FROM job WHERE is_deleted = 0 ORDER BY priority DESC,datetime(created);" - return getJobsByQuery(query: querySql) - } - func getJobsWithDeleted() -> [Job]? { - let querySql = "SELECT * FROM job ORDER BY priority DESC,datetime(created);" - return getJobsByQuery(query: querySql) - } - func getActiveMarkedJobs() -> [Job]? { - let querySql = "SELECT * FROM job WHERE active == 1 AND is_deleted = 0;" - return getJobsByQuery(query: querySql) - } - func getJobsByQuery(query:String)->[Job]?{ - let modifiedQuery: String - if query.lowercased().contains("where") { - modifiedQuery = query.replacingOccurrences(of: "where", with: "WHERE is_deleted = 0 AND", options: .caseInsensitive, range: nil) - } else { - modifiedQuery = query + " WHERE is_deleted = 0" - } - guard let queryStatement = try? prepareStatement(sql: modifiedQuery) else { - return nil - } - defer { - sqlite3_finalize(queryStatement) - } - - var jobs = [Job]() - while(sqlite3_step(queryStatement) == SQLITE_ROW){ - if let job=mapColumnsToJob(sqlStatement: queryStatement){ - jobs.append(job) - } - } - - return jobs - } - - func deletePermanently(job: Job) throws{ - let querySql = "DELETE FROM job WHERE id = ?;" - guard let deleteStatement = try? prepareStatement(sql: querySql) else { - throw SQLiteError.Prepare(message: errorMessage) - } - - defer { - sqlite3_finalize(deleteStatement) - } - - guard sqlite3_bind_text(deleteStatement, 1, job.id.utf8String,-1,nil) == SQLITE_OK else { - throw SQLiteError.Bind(message: errorMessage) - } - - guard sqlite3_step(deleteStatement) == SQLITE_DONE else { - throw SQLiteError.Step(message: errorMessage) - } - } - - func delete(job: Job) throws{ - let querySql = "UPDATE job SET is_deleted = 1 WHERE id = ?;" - guard let deleteStatement = try? prepareStatement(sql: querySql) else { - throw SQLiteError.Prepare(message: errorMessage) - } - - defer { - sqlite3_finalize(deleteStatement) - } - - guard sqlite3_bind_text(deleteStatement, 1, job.id.utf8String,-1,nil) == SQLITE_OK else { - throw SQLiteError.Bind(message: errorMessage) - } - - guard sqlite3_step(deleteStatement) == SQLITE_DONE else { - throw SQLiteError.Step(message: errorMessage) - } - } - func deleteJobsByWorkerName(workerName: NSString) throws{ - let querySql = "UPDATE job SET is_deleted = 1 WHERE worker_name = ?;" - guard let deleteStatement = try? prepareStatement(sql: querySql) else { - throw SQLiteError.Prepare(message: errorMessage) - } - - defer { - sqlite3_finalize(deleteStatement) - } - - guard sqlite3_bind_text(deleteStatement, 1, workerName.utf8String,-1,nil) == SQLITE_OK else { - throw SQLiteError.Bind(message: errorMessage) - } - - guard sqlite3_step(deleteStatement) == SQLITE_DONE else { - throw SQLiteError.Step(message: errorMessage) - } - } - - func update(job: Job) throws{ - let querySql = "UPDATE job SET active = ?, failed = ?, meta_data = ?, attempts = ?, status = ? WHERE id = ?;" - guard let updateStatement = try? prepareStatement(sql: querySql) else { - throw SQLiteError.Prepare(message: errorMessage) - } - - defer { - sqlite3_finalize(updateStatement) - } - - guard (sqlite3_bind_int(updateStatement, 1,job.active) == SQLITE_OK && - sqlite3_bind_text(updateStatement, 2, job.failed.utf8String, -1, nil) == SQLITE_OK && - sqlite3_bind_text(updateStatement, 3, job.metaData.utf8String, -1, nil) == SQLITE_OK && - sqlite3_bind_int(updateStatement, 4, job.attempts) == SQLITE_OK && - sqlite3_bind_text(updateStatement, 5, job.status.utf8String, -1, nil) == SQLITE_OK && - sqlite3_bind_text(updateStatement, 6, job.id.utf8String,-1, nil) == SQLITE_OK - ) else { - throw SQLiteError.Bind(message: errorMessage) - } - guard sqlite3_step(updateStatement) == SQLITE_DONE else { - throw SQLiteError.Step(message: errorMessage) - } - - } - - func mapColumnsToJob(sqlStatement: OpaquePointer?)->Job?{ - if(sqlStatement != nil){ - let idColumnContent = sqlite3_column_text(sqlStatement, 0) - let id = String(cString: idColumnContent!) as NSString - let workerNameColumnContent = sqlite3_column_text(sqlStatement, 1) - let workerName = String(cString: workerNameColumnContent!) as NSString - let active=sqlite3_column_int(sqlStatement, 2) - let payloadColumnContent = sqlite3_column_text(sqlStatement, 3) - let payload = String(cString: payloadColumnContent!) as NSString - let metaDataColumnContent = sqlite3_column_text(sqlStatement, 4) - let metaData = String(cString: metaDataColumnContent!) as NSString - let attempts=sqlite3_column_int(sqlStatement, 5) - let createdColumnContent = sqlite3_column_text(sqlStatement, 6) - let created = String(cString: createdColumnContent!) as NSString - let failedColumnContent = sqlite3_column_text(sqlStatement, 7) - let failed = String(cString: failedColumnContent!) as NSString - let timeout=sqlite3_column_int(sqlStatement, 8) - let priority=sqlite3_column_int(sqlStatement, 9) - let isDeleted = sqlite3_column_int(sqlStatement, 10) - let statusColumnContent = sqlite3_column_text(sqlStatement, 11) - let status = String(cString: statusColumnContent!) as NSString - return Job(id: id, workerName: workerName,active:active,payload:payload,metaData: metaData,attempts: attempts,created: created,failed: failed,timeout: timeout,priority: priority, isDeleted: isDeleted, status: status) - }else{ - return nil - } - } -} diff --git a/ios/JobQueue-Bridging-Header.h b/ios/JobQueue-Bridging-Header.h deleted file mode 100644 index 5fff35c..0000000 --- a/ios/JobQueue-Bridging-Header.h +++ /dev/null @@ -1 +0,0 @@ -#import diff --git a/ios/JobQueue.h b/ios/JobQueue.h deleted file mode 100644 index 0710050..0000000 --- a/ios/JobQueue.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface JobQueue : NSObject - -@end diff --git a/ios/JobQueue.m b/ios/JobQueue.m deleted file mode 100644 index cc21755..0000000 --- a/ios/JobQueue.m +++ /dev/null @@ -1,18 +0,0 @@ -#import - -@interface RCT_EXTERN_MODULE(JobQueue, NSObject) - -RCT_EXTERN_METHOD(addJob:(NSDictionary *)job) -RCT_EXTERN_METHOD(removeJob:(NSDictionary *)job) -RCT_EXTERN_METHOD(removeJobPermanently:(NSDictionary *)job) -RCT_EXTERN_METHOD(updateJob:(NSDictionary *)job) -RCT_EXTERN_METHOD(removeJobsByWorkerName:(NSString *)workerName) -RCT_EXTERN_METHOD(getNextJob:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) -RCT_EXTERN_METHOD(getWorkInProgressJob:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) -RCT_EXTERN_METHOD(getJobsForWorker:(NSString *)name count:(NSInteger) count resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) -RCT_EXTERN_METHOD(getJobsForWorkerWithDeleted:(NSString *)name count:(NSInteger) count resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) -RCT_EXTERN_METHOD(getJobs:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) -RCT_EXTERN_METHOD(getJobsWithDeleted:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) -RCT_EXTERN_METHOD(getActiveMarkedJobs:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) - -@end diff --git a/ios/JobQueue.swift b/ios/JobQueue.swift deleted file mode 100644 index 0a44be7..0000000 --- a/ios/JobQueue.swift +++ /dev/null @@ -1,199 +0,0 @@ -import Foundation -import SQLite3 - -@objc(JobQueue) -public class JobQueue:NSObject{ - var db: SQLiteDatabase?; - public override init() { - super.init() - do { - var path = try FileManager.default.url(for:.libraryDirectory, in: .userDomainMask, appropriateFor: nil, create: true); - path.appendPathComponent("jobdb") - db = try SQLiteDatabase.open(path: path.path) - print("Successfully opened connection to database.") - do { - try db!.createTable(table: Job.self) - } catch { - print(db!.errorMessage) - } - } catch SQLiteError.OpenDatabase(let message) { - print("Unable to open database. Verify that you created the directory described in the Getting Started section.",message) - } catch { - print("Unable to open database. Verify that you created the directory described in the Getting Started section.") - } - - } - - @objc - public func addJob(_ job:[String:Any]){ - if(db != nil){ - do{ - try db?.add(job: Job.createJobFromDictionary(job: job)) - }catch{ - print("Couln't add Job to Database: ",error) - } - } - } - - @objc - public func removeJob(_ job:[String:Any]){ - if(db != nil){ - do{ - try db?.delete(job: Job.createJobFromDictionary(job: job)) - }catch{ - print("Couln't remove job Job to Database: ",error) - } - } - } - @objc - public func removeJobPermanently(_ job:[String:Any]){ - if(db != nil){ - do{ - try db?.deletePermanently(job: Job.createJobFromDictionary(job: job)) - }catch{ - print("Couln't remove job Job to Database: ",error) - } - } - } - @objc - public func removeJobsByWorkerName(_ workerName:String){ - if(db != nil){ - do{ - try db?.deleteJobsByWorkerName(workerName:workerName as NSString) - }catch{ - print("Couln't remove job Job to Database: ",error) - } - } - } - @objc - public func updateJob(_ job:[String:Any]){ - if(db != nil){ - do{ - try db?.update(job: Job.createJobFromDictionary(job: job)) - }catch{ - print("Couln't update job Job to Database: ",error) - } - } - } - - @objc - public func getNextJob(_ resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock){ - if(db != nil){ - if let job = db?.getNextJob(){ - resolve(job.toDictionary()) - }else{ - resolve([String:Any]()) - } - - } - } - @objc - public func getWorkInProgressJob(_ resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock){ - if(db != nil){ - if let job = db?.getWorkInProgressJob(){ - resolve(job.toDictionary()) - }else{ - resolve([String:Any]()) - } - - } - } - - @objc - public func getJobsForWorker(_ name:String, count:Int, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock){ - if(db != nil){ - if let jobs = db?.getJobsForWorker(name: name as NSString, count: Int32(count)){ - var jobsAsDictionaryArray=[[String:Any]]() - for job in jobs{ - var job=job - job.active = 1 - do{ - try db?.update(job: job) - jobsAsDictionaryArray.append(job.toDictionary()) - }catch{ - print("Couln't update job Job to Database: ",error) - } - - } - resolve(jobsAsDictionaryArray) - }else{ - resolve([[String:Any]]()) - } - - } - } - @objc - public func getJobsForWorkerWithDeleted(_ name:String, count:Int, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock){ - if(db != nil){ - if let jobs = db?.getJobsForWorkerWithDeleted(name: name as NSString, count: Int32(count)){ - var jobsAsDictionaryArray=[[String:Any]]() - for job in jobs{ - var job=job - job.active = 1 - do{ - try db?.update(job: job) - jobsAsDictionaryArray.append(job.toDictionary()) - }catch{ - print("Couln't update job Job to Database: ",error) - } - - } - resolve(jobsAsDictionaryArray) - }else{ - resolve([[String:Any]]()) - } - - } - } - - @objc - public func getJobs(_ resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock){ - if(db != nil){ - if let jobs = db?.getJobs(){ - var jobsAsDictionaryArray=[[String:Any]]() - for job in jobs{ - jobsAsDictionaryArray.append(job.toDictionary()) - } - resolve(jobsAsDictionaryArray) - }else{ - resolve([[String:Any]]()) - } - - } - } - @objc - public func getJobsWithDeleted(_ resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock){ - if(db != nil){ - if let jobs = db?.getJobsWithDeleted(){ - var jobsAsDictionaryArray=[[String:Any]]() - for job in jobs{ - jobsAsDictionaryArray.append(job.toDictionary()) - } - resolve(jobsAsDictionaryArray) - }else{ - resolve([[String:Any]]()) - } - - } - } - - @objc - public func getActiveMarkedJobs(_ resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock){ - if(db != nil){ - if let jobs = db?.getActiveMarkedJobs(){ - var jobsAsDictionaryArray=[[String:Any]]() - for job in jobs{ - jobsAsDictionaryArray.append(job.toDictionary()) - } - resolve(jobsAsDictionaryArray) - }else{ - resolve([[String:Any]]()) - } - - } - } - - @objc static func requiresMainQueueSetup() -> Bool { - return false - } -} diff --git a/ios/JobQueue.xcodeproj/project.pbxproj b/ios/JobQueue.xcodeproj/project.pbxproj index 01ca5c8..c5219fb 100644 --- a/ios/JobQueue.xcodeproj/project.pbxproj +++ b/ios/JobQueue.xcodeproj/project.pbxproj @@ -7,7 +7,6 @@ objects = { /* Begin PBXBuildFile section */ - B3E7B58A1CC2AC0600A0062D /* JobQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* JobQueue.m */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -24,15 +23,6 @@ /* Begin PBXFileReference section */ 134814201AA4EA6300B7C361 /* libJobQueue.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libJobQueue.a; sourceTree = BUILT_PRODUCTS_DIR; }; - B3E7B5881CC2AC0600A0062D /* JobQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JobQueue.h; sourceTree = ""; }; - B3E7B5891CC2AC0600A0062D /* JobQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JobQueue.m; sourceTree = ""; }; - F4297A7A22FA3484000FE33E /* JobQueue-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "JobQueue-Bridging-Header.h"; sourceTree = ""; }; - F4297A7B22FA3484000FE33E /* JobQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JobQueue.swift; sourceTree = ""; }; - F4297A8A22FB720E000FE33E /* JobQueue.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = JobQueue.m; path = "/Users/simon/Developer/Projects/ReactNative/react-native-job-queue/ios/JobQueue.m"; sourceTree = ""; }; - F4297A8B22FB720E000FE33E /* JobQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = JobQueue.swift; path = "/Users/simon/Developer/Projects/ReactNative/react-native-job-queue/ios/JobQueue.swift"; sourceTree = ""; }; - F4297A8C22FB720E000FE33E /* Job.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Job.swift; path = "/Users/simon/Developer/Projects/ReactNative/react-native-job-queue/ios/Job.swift"; sourceTree = ""; }; - F4297A8D22FB720E000FE33E /* SQLiteDatabase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SQLiteDatabase.swift; path = "/Users/simon/Developer/Projects/ReactNative/react-native-job-queue/ios/SQLiteDatabase.swift"; sourceTree = ""; }; - F4297A8E22FB720E000FE33E /* SQLTable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SQLTable.swift; path = "/Users/simon/Developer/Projects/ReactNative/react-native-job-queue/ios/SQLTable.swift"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -57,16 +47,7 @@ 58B511D21A9E6C8500147676 = { isa = PBXGroup; children = ( - F4297A7B22FA3484000FE33E /* JobQueue.swift */, - F4297A8C22FB720E000FE33E /* Job.swift */, - F4297A8A22FB720E000FE33E /* JobQueue.m */, - F4297A8B22FB720E000FE33E /* JobQueue.swift */, - F4297A8D22FB720E000FE33E /* SQLiteDatabase.swift */, - F4297A8E22FB720E000FE33E /* SQLTable.swift */, - B3E7B5881CC2AC0600A0062D /* JobQueue.h */, - B3E7B5891CC2AC0600A0062D /* JobQueue.m */, 134814211AA4EA7D00B7C361 /* Products */, - F4297A7A22FA3484000FE33E /* JobQueue-Bridging-Header.h */, ); sourceTree = ""; }; @@ -128,7 +109,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - B3E7B58A1CC2AC0600A0062D /* JobQueue.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -243,7 +223,6 @@ OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = JobQueue; SKIP_INSTALL = YES; - SWIFT_OBJC_BRIDGING_HEADER = "JobQueue-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; }; @@ -264,7 +243,6 @@ OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = JobQueue; SKIP_INSTALL = YES; - SWIFT_OBJC_BRIDGING_HEADER = "JobQueue-Bridging-Header.h"; SWIFT_VERSION = 5.0; }; name = Release; diff --git a/ios/SQLTable.swift b/ios/SQLTable.swift deleted file mode 100644 index 116fb7b..0000000 --- a/ios/SQLTable.swift +++ /dev/null @@ -1,3 +0,0 @@ -protocol SQLTable { - static var createStatement: String { get } -} diff --git a/ios/SQLiteDatabase.swift b/ios/SQLiteDatabase.swift deleted file mode 100644 index 101b06e..0000000 --- a/ios/SQLiteDatabase.swift +++ /dev/null @@ -1,68 +0,0 @@ -import SQLite3 -class SQLiteDatabase { - fileprivate let dbPointer: OpaquePointer? - - fileprivate init(dbPointer: OpaquePointer?) { - self.dbPointer = dbPointer - } - - deinit { - sqlite3_close(dbPointer) - } - - static func open(path: String) throws -> SQLiteDatabase { - var db: OpaquePointer? = nil - if sqlite3_open(path, &db) == SQLITE_OK { - return SQLiteDatabase(dbPointer: db) - } else { - defer { - if db != nil { - sqlite3_close(db) - } - } - if let errorPointer = sqlite3_errmsg(db) { - let message = String.init(cString: errorPointer) - throw SQLiteError.OpenDatabase(message: message) - } else { - throw SQLiteError.OpenDatabase(message: "No error message provided from sqlite.") - } - } - } - - var errorMessage: String { - if let errorPointer = sqlite3_errmsg(dbPointer) { - let errorMessage = String(cString: errorPointer) - return errorMessage - } else { - return "No error message provided from sqlite." - } - } - func prepareStatement(sql: String) throws -> OpaquePointer? { - var statement: OpaquePointer? = nil - guard sqlite3_prepare_v2(dbPointer, sql, -1, &statement, nil) == SQLITE_OK else { - throw SQLiteError.Prepare(message: errorMessage) - } - - return statement - } - func createTable(table: SQLTable.Type) throws { - // 1 - let createTableStatement = try prepareStatement(sql: table.createStatement) - // 2 - defer { - sqlite3_finalize(createTableStatement) - } - // 3 - guard sqlite3_step(createTableStatement) == SQLITE_DONE else { - throw SQLiteError.Step(message: errorMessage) - } - print("\(table) table created.") - } -} - -enum SQLiteError: Error { - case OpenDatabase(message: String) - case Prepare(message: String) - case Step(message: String) - case Bind(message: String) -} diff --git a/lib/commonjs/Queue.js b/lib/commonjs/Queue.js index 58db68f..cbcc75c 100644 --- a/lib/commonjs/Queue.js +++ b/lib/commonjs/Queue.js @@ -99,7 +99,7 @@ class Queue extends _eventemitter.default { return; } let nextJob = await this.jobStore.getWorkInProgressJob(); - if (!nextJob) { + if (!this.isJobNotEmpty(nextJob)) { nextJob = await this.jobStore.getNextJob(); } if (this.isJobNotEmpty(nextJob)) { diff --git a/lib/commonjs/Queue.js.map b/lib/commonjs/Queue.js.map index 36e8b74..535ceb0 100644 --- a/lib/commonjs/Queue.js.map +++ b/lib/commonjs/Queue.js.map @@ -1 +1 @@ -{"version":3,"names":["_reactNative","require","_Job","_Uuid","_Worker","_eventemitter","_interopRequireDefault","_Queue","e","__esModule","default","_defineProperty","r","t","_toPropertyKey","Object","defineProperty","value","enumerable","configurable","writable","i","_toPrimitive","Symbol","toPrimitive","call","TypeError","String","Number","QueueError","Error","constructor","message","code","name","exports","Queue","EventEmitter","instance","queueInstance","isRunning","isActive","registeredWorkers","workers","job","jobStore","updateJob","active","FALSE","finishQueue","nextJob","getWorkInProgressJob","getNextJob","isJobNotEmpty","nextJobs","getJobsForWorker","workerName","processingJobs","map","limitExecution","excuteJob","Promise","all","isExecuting","scheduleQueue","executer","rawJob","resolve","enqueueJobExecuter","isExecuterAvailable","runExecuter","queuedJobExecuter","push","bind","length","shift","worker","payload","JSON","parse","status","stringify","emit","activeJobCount","promise","execute","runningJobPromises","id","triggerSuccess","removeJob","err","error","attempts","errors","failedAttempts","metaData","failed","Date","toISOString","triggerFailure","failedJob","decreaseExecutionCount","triggerCompletion","executedJobs","NativeModules","JobQueue","timeoutId","updateInterval","onQueueFinish","concurrency","getJobs","getJobsWithDeleted","removeJobPermanent","removeJobPermanently","requeueJob","newJob","start","then","console","log","catch","configure","options","addWorker","removeWorker","deleteRelatedJobs","removeJobsByWorkerName","addJob","timeout","priority","startQueue","Uuid","v4","created","isDeleted","resetActiveJobs","stop","cancelJob","jobId","exception","undefined","CANCEL","warn","cancelAllActiveJobs","jobs","forEach","Boolean","cancelActiveJob","activeMarkedJobs","getActiveMarkedJobs","resetTasks","resetActiveJob","AppState","currentState","Platform","OS","setTimeout","runQueue","keys","clearTimeout","isBusy","availableExecuters","getJobsForAlternateWorker","getJobsForWorkerWithDeleted","_default"],"sources":["Queue.ts"],"sourcesContent":["/* eslint-disable no-extra-boolean-cast */\n/* eslint-disable @typescript-eslint/no-empty-function */\nimport { AppState, NativeModules, Platform } from 'react-native';\n\nimport { FALSE, Job, RawJob, TRUE } from './models/Job';\nimport { JobStore } from './models/JobStore';\nimport { Uuid } from './utils/Uuid';\nimport { Worker, CANCEL, CancellablePromise } from './Worker';\n\n\nimport EventEmitter from 'eventemitter3';\n\ntype QueueErrorType = \"cancelled\" | \"error\";\n\nexport class QueueError extends Error {\n code: QueueErrorType;\n constructor(message: string, code: QueueErrorType = \"error\") {\n super(message);\n this.name = 'QueueError';\n this.code = code;\n }\n}\n\n/**\n * Events emitted by the Queue.\n */\nexport interface QueueEvents {\n /**\n * Fired when a worker is added.\n * @param workerName Name of the worker.\n */\n workerAdded: (workerName: string) => void;\n\n /**\n * Fired when a job is added to the queue.\n * @param job The RawJob that was added.\n */\n jobAdded: (job: RawJob) => void;\n\n /**\n * Fired when a job starts processing.\n * @param job The RawJob that started.\n */\n jobStarted: (job: RawJob) => void;\n\n /**\n * Fired when a job completes successfully.\n * @param job The Job with payload that succeeded.\n */\n jobSucceeded: (job: Job) => void;\n\n /**\n * Fired when a job fails.\n * @param job The RawJob that failed.\n * @param error The error thrown.\n */\n jobFailed: (job: RawJob, error: Error) => void;\n\n /**\n * Fired when a job fails.\n * @param job The RawJob that failed.\n * @param error The error thrown.\n */\n jobCancelled: (job: RawJob) => void;\n\n /**\n * Fired when a job completes (regardless of success or failure).\n * @param job The RawJob that finished.\n */\n jobCompleted: (job: RawJob) => void;\n\n /**\n * Fired when a job is deleted.\n * @param job The RawJob that was deleted.\n */\n jobDeleted: (job: RawJob) => void\n\n /**\n * Fired when a job is requeued.\n * @param job The RawJob that was requeued.\n */\n jobRequeued: (job: RawJob) => void\n}\n\n\n/**\n * Options to configure the queue\n */\nexport interface QueueOptions {\n /**\n * A callback function which is called after the queue has been stopped\n * @parameter executedJobs\n */\n onQueueFinish?: (executedJobs: Array>) => void;\n /**\n * Interval in which the queue checks for new jobs to execute\n */\n updateInterval?: number;\n concurrency?: number;\n}\n/**\n * ## Usage\n *\n * ```typescript\n * import queue from 'react-native-job-queue'\n *\n * queue.configure({onQueueFinish:(executedJobs:Job[])=>{\n * console.log(\"Queue stopped and executed\",executedJobs)\n * }});\n * queue.addWorker(new Worker(\"testWorker\",async(payload, id)=>{\n * return new Promise((resolve) => {\n * setTimeout(() => {\n * console.log('Executing jobId', id, 'with:', payload.text);\n * resolve();\n * }, payload.delay);});\n * }))\n * queue.addJob(\"testWorker\",{text:\"Job example payload content text\",delay:5000})\n * ```\n */\nexport class Queue extends EventEmitter {\n static get instance() {\n if (this.queueInstance) {\n return this.queueInstance;\n } else {\n this.queueInstance = new Queue();\n return this.queueInstance;\n }\n }\n /**\n * @returns true if the Queue is running and false otherwise\n */\n get isRunning() {\n return this.isActive;\n }\n /**\n * @returns the workers map (readonly)\n */\n get registeredWorkers() {\n return this.workers;\n }\n private static queueInstance: Queue | null;\n private emitter: EventEmitter = new EventEmitter();\n\n private jobStore: JobStore;\n private workers: { [key: string]: Worker };\n private isActive: boolean;\n\n private timeoutId: number;\n private executedJobs: Array>;\n private activeJobCount: number;\n\n private concurrency: number;\n private updateInterval: number;\n private onQueueFinish: (executedJobs: Array>) => void;\n\n private queuedJobExecuter: any[] = [];\n private runningJobPromises: { [key: string]: CancellablePromise };\n\n private constructor() {\n super();\n this.jobStore = NativeModules.JobQueue;\n this.workers = {};\n this.runningJobPromises = {};\n this.isActive = false;\n\n this.timeoutId = 0;\n this.executedJobs = [];\n this.activeJobCount = 0;\n\n this.updateInterval = 10;\n this.onQueueFinish = (executedJobs: Array>) => { };\n this.concurrency = -1;\n }\n\n\n\n /**\n * @returns a promise that resolves all jobs of jobStore\n */\n async getJobs() {\n return await this.jobStore.getJobs();\n }\n async getJobsWithDeleted() {\n return await this.jobStore.getJobsWithDeleted();\n }\n /**\n * @param job the job to be deleted\n */\n removeJob(job: RawJob) {\n this.jobStore.removeJob(job);\n this.emit(\"jobDeleted\", job)\n }\n removeJobPermanent(job: RawJob) {\n this.jobStore.removeJobPermanently(job);\n this.emit(\"jobDeleted\", job)\n }\n /**\n * @param job the job which should be requeued\n */\n requeueJob(job: RawJob) {\n const newJob = { ...job, failed: '', status: \"idle\", active: FALSE } as RawJob;\n this.jobStore.updateJob(newJob);\n this.emit(\"jobRequeued\", newJob)\n if (!this.isActive) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n this.start().then(() => {\n console.log(\"Queue restarted\")\n }).catch(() => {\n console.log(\"Queue could not be restarted\")\n });\n }\n }\n\n configure(options: QueueOptions) {\n const {\n onQueueFinish = (executedJobs: Array>) => { },\n updateInterval = 10,\n concurrency = -1,\n } = options;\n this.onQueueFinish = onQueueFinish;\n this.updateInterval = updateInterval;\n this.concurrency = concurrency;\n }\n /**\n * adds a [[Worker]] to the queue which can execute Jobs\n * @param worker\n */\n addWorker(worker: Worker) {\n if (this.workers[worker.name]) {\n throw new QueueError(`Worker \"${worker.name}\" already exists.`, \"error\");\n }\n this.workers[worker.name] = worker;\n this.emit('workerAdded', worker.name);\n }\n\n /**\n * removes worker from queue\n *\n * @param name\n * @param [deleteRelatedJobs=false] removes all queued jobs releated to the worker if set to true\n */\n removeWorker(name: string, deleteRelatedJobs = false) {\n delete this.workers[name];\n if (deleteRelatedJobs) {\n this.jobStore.removeJobsByWorkerName(name);\n }\n }\n\n /**\n * adds a job to the queue\n * @param workerName name of the worker which should be used to excute the job\n * @param [payload={}] payload which is passed as parameter to the executer\n * @param [options={ attempts: 0, timeout: 0, priority: 0 }] options to set max attempts, a timeout and a priority\n * @param [startQueue=true] if set to false the queue won't start automaticly when adding a job\n * @returns job id\n */\n addJob

(\n workerName: string,\n payload: P,\n options = { attempts: 0, timeout: 0, priority: 0 },\n startQueue = true\n ) {\n const { attempts = 0, timeout = 0, priority = 0 } = options;\n const id: string = Uuid.v4();\n const job: RawJob = {\n id,\n payload: JSON.stringify(payload || {}),\n metaData: JSON.stringify({ failedAttempts: 0, errors: [] }),\n active: FALSE,\n created: new Date().toISOString(),\n failed: '',\n workerName,\n attempts,\n timeout,\n priority,\n isDeleted: false,\n status: \"idle\"\n };\n if (!this.workers[job.workerName]) {\n throw new QueueError(`Missing worker with name ${job.workerName}`);\n }\n\n this.jobStore.addJob(job);\n this.emit('jobAdded', job);\n if (startQueue && !this.isActive) {\n this.start();\n }\n\n return id;\n }\n /**\n * starts the queue to execute queued jobs\n */\n async start() {\n if (!this.isActive) {\n this.isActive = true;\n this.executedJobs = [];\n await this.resetActiveJobs();\n this.scheduleQueue();\n }\n }\n /**\n * stop the queue from executing queued jobs\n */\n stop() {\n this.isActive = false;\n }\n\n /**\n * cancel running job\n */\n cancelJob(jobId: string, exception?: Error) {\n const promise = this.runningJobPromises[jobId];\n if (promise !== undefined && typeof promise[CANCEL] === 'function') {\n promise[CANCEL](exception || new QueueError(`job canceled`, \"cancelled\"));\n } else if (!promise[CANCEL]) {\n console.warn('Worker does not have a cancel method implemented');\n } else {\n throw new QueueError(`Job with id ${jobId} not currently running`, \"error\");\n }\n }\n async cancelAllActiveJobs() {\n const jobs = await this.jobStore.getJobs()\n\n jobs.forEach((job) => {\n const newJob = { ...job, ...{ active: FALSE, status: \"cancelled\" } };\n const isRunning = this.runningJobPromises[job.id];\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n if (!!Boolean(isRunning)) {\n this.cancelJob(job.id, new QueueError(`Job with id ${job.id} cancelled`, \"cancelled\"));\n }\n this.jobStore.updateJob(newJob as RawJob);\n this.emit('jobCancelled', newJob as RawJob);\n })\n }\n cancelActiveJob(job: RawJob) {\n const newJob = { ...job, ...{ active: FALSE, status: \"cancelled\" } };\n\n const isRunning = this.runningJobPromises[job.id];\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n if (!!isRunning) {\n this.cancelJob(job.id, new QueueError(`Job with id ${job.id} cancelled`, \"cancelled\"));\n }\n\n this.jobStore.updateJob(newJob as RawJob);\n\n this.emit('jobCancelled', newJob as RawJob);\n }\n\n private resetActiveJob = (job: RawJob) => {\n this.jobStore.updateJob({ ...job, ...{ active: FALSE } });\n };\n private async resetActiveJobs() {\n const activeMarkedJobs = await this.jobStore.getActiveMarkedJobs();\n const resetTasks = activeMarkedJobs.map(this.resetActiveJob);\n await Promise.all(resetTasks);\n }\n private scheduleQueue() {\n if (AppState.currentState === 'active' && Platform.OS === \"ios\") {\n this.timeoutId = setTimeout(this.runQueue, this.updateInterval);\n } else {\n this.runQueue();\n }\n }\n private runQueue = async () => {\n if (!this.isActive) {\n this.finishQueue();\n return;\n }\n let nextJob = await this.jobStore.getWorkInProgressJob();\n if (!nextJob) {\n nextJob = await this.jobStore.getNextJob();\n }\n if (this.isJobNotEmpty(nextJob)) {\n const nextJobs = await this.getJobsForWorker(nextJob.workerName);\n const processingJobs = nextJobs.map(async (job) => this.limitExecution(this.excuteJob, job));\n await Promise.all(processingJobs);\n } else if (!this.isExecuting()) {\n this.finishQueue();\n return;\n }\n this.scheduleQueue();\n };\n\n private isJobNotEmpty(rawJob: RawJob | {}) {\n return Object.keys(rawJob).length > 0;\n }\n\n private limitExecution = async (executer: (rawJob: RawJob) => Promise, rawJob: RawJob) => {\n return new Promise(async (resolve) => await this.enqueueJobExecuter(executer, resolve, rawJob));\n };\n\n private enqueueJobExecuter = async (\n executer: (rawJob: RawJob) => Promise,\n resolve: (_: unknown) => void,\n rawJob: RawJob\n ) => {\n if (this.isExecuterAvailable()) {\n await this.runExecuter(executer, resolve, rawJob);\n } else {\n this.queuedJobExecuter.push(this.runExecuter.bind(null, executer, resolve, rawJob));\n }\n };\n\n private runExecuter = async (\n executer: (rawJob: RawJob) => Promise,\n resolve: (_: unknown) => void,\n rawJob: RawJob\n ) => {\n try {\n await executer(rawJob);\n } finally {\n resolve(true);\n if (this.queuedJobExecuter.length > 0 && this.isExecuterAvailable()) {\n await this.queuedJobExecuter.shift()();\n }\n }\n };\n private isExecuterAvailable() {\n return this.concurrency <= 0 || this.activeJobCount < this.concurrency;\n }\n private isExecuting() {\n return this.activeJobCount > 0;\n }\n\n private finishQueue() {\n this.onQueueFinish(this.executedJobs);\n this.isActive = false;\n clearTimeout(this.timeoutId);\n }\n\n async getJobsForWorker(workerName: string) {\n const { isBusy, availableExecuters } = this.workers[workerName];\n if (!isBusy) {\n return await this.jobStore.getJobsForWorker(workerName, availableExecuters);\n } else {\n return await this.getJobsForAlternateWorker();\n }\n }\n\n async getJobsForWorkerWithDeleted(workerName: string) {\n const { isBusy, availableExecuters } = this.workers[workerName];\n if (!isBusy) {\n return await this.jobStore.getJobsForWorkerWithDeleted(workerName, availableExecuters);\n } else {\n return await this.getJobsForAlternateWorker();\n }\n }\n\n private async getJobsForAlternateWorker() {\n for (const workerName of Object.keys(this.workers)) {\n const { isBusy, availableExecuters } = this.workers[workerName];\n let nextJobs: RawJob[] = [];\n if (!isBusy) {\n nextJobs = await this.jobStore.getJobsForWorker(workerName, availableExecuters);\n }\n if (nextJobs.length > 0) {\n return nextJobs;\n }\n }\n return [];\n }\n\n private excuteJob = async (rawJob: RawJob) => {\n const worker = this.workers[rawJob.workerName];\n const payload = JSON.parse(rawJob.payload) as Worker;\n const job = { ...rawJob, ...{ payload } } as Job;\n\n try {\n job.status = \"processing\";\n this.jobStore.updateJob({ ...job, payload: JSON.stringify(payload) });\n this.emit('jobStarted', job);\n\n this.activeJobCount++;\n if (!this.workers[rawJob.workerName]) {\n throw new QueueError(`Missing worker with name ${rawJob.workerName}`, \"error\");\n }\n const promise = worker.execute(rawJob);\n\n this.runningJobPromises[rawJob.id] = promise;\n await promise;\n\n worker.triggerSuccess(job);\n job.status = \"finished\";\n this.jobStore.updateJob({ ...job, payload: JSON.stringify(payload) });\n this.jobStore.removeJob(rawJob);\n this.emit('jobSucceeded', job);\n } catch (err) {\n const error = err as QueueError;\n const { attempts } = rawJob;\n // eslint-disable-next-line prefer-const\n let { errors, failedAttempts } = JSON.parse(rawJob.metaData) as { errors: string[]; failedAttempts: number };\n failedAttempts++;\n let failed = '';\n if (failedAttempts >= attempts) {\n failed = new Date().toISOString();\n }\n const metaData = JSON.stringify({ errors: [...errors, error], failedAttempts });\n worker.triggerFailure({ ...job, metaData, failed }, error);\n const failedJob = { ...rawJob, ...{ active: FALSE, metaData, failed, status: error.code === \"cancelled\" ? \"cancelled\" : \"failed\" } } as RawJob;\n this.jobStore.updateJob(failedJob);\n this.emit('jobFailed', failedJob, error);\n } finally {\n delete this.runningJobPromises[job.id];\n worker.decreaseExecutionCount();\n worker.triggerCompletion(job);\n this.emit('jobCompleted', { ...job });\n this.executedJobs.push(rawJob);\n this.activeJobCount--;\n }\n };\n}\nexport default Queue.instance;\n"],"mappings":"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","ignoreList":[]} \ No newline at end of file +{"version":3,"names":["_reactNative","require","_Job","_Uuid","_Worker","_eventemitter","_interopRequireDefault","_Queue","e","__esModule","default","_defineProperty","r","t","_toPropertyKey","Object","defineProperty","value","enumerable","configurable","writable","i","_toPrimitive","Symbol","toPrimitive","call","TypeError","String","Number","QueueError","Error","constructor","message","code","name","exports","Queue","EventEmitter","instance","queueInstance","isRunning","isActive","registeredWorkers","workers","job","jobStore","updateJob","active","FALSE","finishQueue","nextJob","getWorkInProgressJob","isJobNotEmpty","getNextJob","nextJobs","getJobsForWorker","workerName","processingJobs","map","limitExecution","excuteJob","Promise","all","isExecuting","scheduleQueue","executer","rawJob","resolve","enqueueJobExecuter","isExecuterAvailable","runExecuter","queuedJobExecuter","push","bind","length","shift","worker","payload","JSON","parse","status","stringify","emit","activeJobCount","promise","execute","runningJobPromises","id","triggerSuccess","removeJob","err","error","attempts","errors","failedAttempts","metaData","failed","Date","toISOString","triggerFailure","failedJob","decreaseExecutionCount","triggerCompletion","executedJobs","NativeModules","JobQueue","timeoutId","updateInterval","onQueueFinish","concurrency","getJobs","getJobsWithDeleted","removeJobPermanent","removeJobPermanently","requeueJob","newJob","start","then","console","log","catch","configure","options","addWorker","removeWorker","deleteRelatedJobs","removeJobsByWorkerName","addJob","timeout","priority","startQueue","Uuid","v4","created","isDeleted","resetActiveJobs","stop","cancelJob","jobId","exception","undefined","CANCEL","warn","cancelAllActiveJobs","jobs","forEach","Boolean","cancelActiveJob","activeMarkedJobs","getActiveMarkedJobs","resetTasks","resetActiveJob","AppState","currentState","Platform","OS","setTimeout","runQueue","keys","clearTimeout","isBusy","availableExecuters","getJobsForAlternateWorker","getJobsForWorkerWithDeleted","_default"],"sources":["Queue.ts"],"sourcesContent":["/* eslint-disable no-extra-boolean-cast */\n/* eslint-disable @typescript-eslint/no-empty-function */\nimport { AppState, NativeModules, Platform } from 'react-native';\n\nimport { FALSE, Job, RawJob, TRUE } from './models/Job';\nimport { JobStore } from './models/JobStore';\nimport { Uuid } from './utils/Uuid';\nimport { Worker, CANCEL, CancellablePromise } from './Worker';\n\n\nimport EventEmitter from 'eventemitter3';\n\ntype QueueErrorType = \"cancelled\" | \"error\";\n\nexport class QueueError extends Error {\n code: QueueErrorType;\n constructor(message: string, code: QueueErrorType = \"error\") {\n super(message);\n this.name = 'QueueError';\n this.code = code;\n }\n}\n\n/**\n * Events emitted by the Queue.\n */\nexport interface QueueEvents {\n /**\n * Fired when a worker is added.\n * @param workerName Name of the worker.\n */\n workerAdded: (workerName: string) => void;\n\n /**\n * Fired when a job is added to the queue.\n * @param job The RawJob that was added.\n */\n jobAdded: (job: RawJob) => void;\n\n /**\n * Fired when a job starts processing.\n * @param job The RawJob that started.\n */\n jobStarted: (job: RawJob) => void;\n\n /**\n * Fired when a job completes successfully.\n * @param job The Job with payload that succeeded.\n */\n jobSucceeded: (job: Job) => void;\n\n /**\n * Fired when a job fails.\n * @param job The RawJob that failed.\n * @param error The error thrown.\n */\n jobFailed: (job: RawJob, error: Error) => void;\n\n /**\n * Fired when a job fails.\n * @param job The RawJob that failed.\n * @param error The error thrown.\n */\n jobCancelled: (job: RawJob) => void;\n\n /**\n * Fired when a job completes (regardless of success or failure).\n * @param job The RawJob that finished.\n */\n jobCompleted: (job: RawJob) => void;\n\n /**\n * Fired when a job is deleted.\n * @param job The RawJob that was deleted.\n */\n jobDeleted: (job: RawJob) => void\n\n /**\n * Fired when a job is requeued.\n * @param job The RawJob that was requeued.\n */\n jobRequeued: (job: RawJob) => void\n}\n\n\n/**\n * Options to configure the queue\n */\nexport interface QueueOptions {\n /**\n * A callback function which is called after the queue has been stopped\n * @parameter executedJobs\n */\n onQueueFinish?: (executedJobs: Array>) => void;\n /**\n * Interval in which the queue checks for new jobs to execute\n */\n updateInterval?: number;\n concurrency?: number;\n}\n/**\n * ## Usage\n *\n * ```typescript\n * import queue from 'react-native-job-queue'\n *\n * queue.configure({onQueueFinish:(executedJobs:Job[])=>{\n * console.log(\"Queue stopped and executed\",executedJobs)\n * }});\n * queue.addWorker(new Worker(\"testWorker\",async(payload, id)=>{\n * return new Promise((resolve) => {\n * setTimeout(() => {\n * console.log('Executing jobId', id, 'with:', payload.text);\n * resolve();\n * }, payload.delay);});\n * }))\n * queue.addJob(\"testWorker\",{text:\"Job example payload content text\",delay:5000})\n * ```\n */\nexport class Queue extends EventEmitter {\n static get instance() {\n if (this.queueInstance) {\n return this.queueInstance;\n } else {\n this.queueInstance = new Queue();\n return this.queueInstance;\n }\n }\n /**\n * @returns true if the Queue is running and false otherwise\n */\n get isRunning() {\n return this.isActive;\n }\n /**\n * @returns the workers map (readonly)\n */\n get registeredWorkers() {\n return this.workers;\n }\n private static queueInstance: Queue | null;\n private emitter: EventEmitter = new EventEmitter();\n\n private jobStore: JobStore;\n private workers: { [key: string]: Worker };\n private isActive: boolean;\n\n private timeoutId: number;\n private executedJobs: Array>;\n private activeJobCount: number;\n\n private concurrency: number;\n private updateInterval: number;\n private onQueueFinish: (executedJobs: Array>) => void;\n\n private queuedJobExecuter: any[] = [];\n private runningJobPromises: { [key: string]: CancellablePromise };\n\n private constructor() {\n super();\n this.jobStore = NativeModules.JobQueue;\n this.workers = {};\n this.runningJobPromises = {};\n this.isActive = false;\n\n this.timeoutId = 0;\n this.executedJobs = [];\n this.activeJobCount = 0;\n\n this.updateInterval = 10;\n this.onQueueFinish = (executedJobs: Array>) => { };\n this.concurrency = -1;\n }\n\n\n\n /**\n * @returns a promise that resolves all jobs of jobStore\n */\n async getJobs() {\n return await this.jobStore.getJobs();\n }\n async getJobsWithDeleted() {\n return await this.jobStore.getJobsWithDeleted();\n }\n /**\n * @param job the job to be deleted\n */\n removeJob(job: RawJob) {\n this.jobStore.removeJob(job);\n this.emit(\"jobDeleted\", job)\n }\n removeJobPermanent(job: RawJob) {\n this.jobStore.removeJobPermanently(job);\n this.emit(\"jobDeleted\", job)\n }\n /**\n * @param job the job which should be requeued\n */\n requeueJob(job: RawJob) {\n const newJob = { ...job, failed: '', status: \"idle\", active: FALSE } as RawJob;\n this.jobStore.updateJob(newJob);\n this.emit(\"jobRequeued\", newJob)\n if (!this.isActive) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n this.start().then(() => {\n console.log(\"Queue restarted\")\n }).catch(() => {\n console.log(\"Queue could not be restarted\")\n });\n }\n }\n\n configure(options: QueueOptions) {\n const {\n onQueueFinish = (executedJobs: Array>) => { },\n updateInterval = 10,\n concurrency = -1,\n } = options;\n this.onQueueFinish = onQueueFinish;\n this.updateInterval = updateInterval;\n this.concurrency = concurrency;\n }\n /**\n * adds a [[Worker]] to the queue which can execute Jobs\n * @param worker\n */\n addWorker(worker: Worker) {\n if (this.workers[worker.name]) {\n throw new QueueError(`Worker \"${worker.name}\" already exists.`, \"error\");\n }\n this.workers[worker.name] = worker;\n this.emit('workerAdded', worker.name);\n }\n\n /**\n * removes worker from queue\n *\n * @param name\n * @param [deleteRelatedJobs=false] removes all queued jobs releated to the worker if set to true\n */\n removeWorker(name: string, deleteRelatedJobs = false) {\n delete this.workers[name];\n if (deleteRelatedJobs) {\n this.jobStore.removeJobsByWorkerName(name);\n }\n }\n\n /**\n * adds a job to the queue\n * @param workerName name of the worker which should be used to excute the job\n * @param [payload={}] payload which is passed as parameter to the executer\n * @param [options={ attempts: 0, timeout: 0, priority: 0 }] options to set max attempts, a timeout and a priority\n * @param [startQueue=true] if set to false the queue won't start automaticly when adding a job\n * @returns job id\n */\n addJob

(\n workerName: string,\n payload: P,\n options = { attempts: 0, timeout: 0, priority: 0 },\n startQueue = true\n ) {\n const { attempts = 0, timeout = 0, priority = 0 } = options;\n const id: string = Uuid.v4();\n const job: RawJob = {\n id,\n payload: JSON.stringify(payload || {}),\n metaData: JSON.stringify({ failedAttempts: 0, errors: [] }),\n active: FALSE,\n created: new Date().toISOString(),\n failed: '',\n workerName,\n attempts,\n timeout,\n priority,\n isDeleted: false,\n status: \"idle\"\n };\n if (!this.workers[job.workerName]) {\n throw new QueueError(`Missing worker with name ${job.workerName}`);\n }\n\n this.jobStore.addJob(job);\n this.emit('jobAdded', job);\n if (startQueue && !this.isActive) {\n this.start();\n }\n\n return id;\n }\n /**\n * starts the queue to execute queued jobs\n */\n async start() {\n if (!this.isActive) {\n this.isActive = true;\n this.executedJobs = [];\n await this.resetActiveJobs();\n this.scheduleQueue();\n }\n }\n /**\n * stop the queue from executing queued jobs\n */\n stop() {\n this.isActive = false;\n }\n\n /**\n * cancel running job\n */\n cancelJob(jobId: string, exception?: Error) {\n const promise = this.runningJobPromises[jobId];\n if (promise !== undefined && typeof promise[CANCEL] === 'function') {\n promise[CANCEL](exception || new QueueError(`job canceled`, \"cancelled\"));\n } else if (!promise[CANCEL]) {\n console.warn('Worker does not have a cancel method implemented');\n } else {\n throw new QueueError(`Job with id ${jobId} not currently running`, \"error\");\n }\n }\n async cancelAllActiveJobs() {\n const jobs = await this.jobStore.getJobs()\n\n jobs.forEach((job) => {\n const newJob = { ...job, ...{ active: FALSE, status: \"cancelled\" } };\n const isRunning = this.runningJobPromises[job.id];\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n if (!!Boolean(isRunning)) {\n this.cancelJob(job.id, new QueueError(`Job with id ${job.id} cancelled`, \"cancelled\"));\n }\n this.jobStore.updateJob(newJob as RawJob);\n this.emit('jobCancelled', newJob as RawJob);\n })\n }\n cancelActiveJob(job: RawJob) {\n const newJob = { ...job, ...{ active: FALSE, status: \"cancelled\" } };\n\n const isRunning = this.runningJobPromises[job.id];\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n if (!!isRunning) {\n this.cancelJob(job.id, new QueueError(`Job with id ${job.id} cancelled`, \"cancelled\"));\n }\n\n this.jobStore.updateJob(newJob as RawJob);\n\n this.emit('jobCancelled', newJob as RawJob);\n }\n\n private resetActiveJob = (job: RawJob) => {\n this.jobStore.updateJob({ ...job, ...{ active: FALSE } });\n };\n private async resetActiveJobs() {\n const activeMarkedJobs = await this.jobStore.getActiveMarkedJobs();\n const resetTasks = activeMarkedJobs.map(this.resetActiveJob);\n await Promise.all(resetTasks);\n }\n private scheduleQueue() {\n if (AppState.currentState === 'active' && Platform.OS === \"ios\") {\n this.timeoutId = setTimeout(this.runQueue, this.updateInterval);\n } else {\n this.runQueue();\n }\n }\n private runQueue = async () => {\n if (!this.isActive) {\n this.finishQueue();\n return;\n }\n let nextJob = await this.jobStore.getWorkInProgressJob();\n if (!this.isJobNotEmpty(nextJob)) {\n nextJob = await this.jobStore.getNextJob();\n }\n if (this.isJobNotEmpty(nextJob)) {\n const nextJobs = await this.getJobsForWorker(nextJob.workerName);\n const processingJobs = nextJobs.map(async (job) => this.limitExecution(this.excuteJob, job));\n await Promise.all(processingJobs);\n } else if (!this.isExecuting()) {\n this.finishQueue();\n return;\n }\n this.scheduleQueue();\n };\n\n private isJobNotEmpty(rawJob: RawJob | {}) {\n return Object.keys(rawJob).length > 0;\n }\n\n private limitExecution = async (executer: (rawJob: RawJob) => Promise, rawJob: RawJob) => {\n return new Promise(async (resolve) => await this.enqueueJobExecuter(executer, resolve, rawJob));\n };\n\n private enqueueJobExecuter = async (\n executer: (rawJob: RawJob) => Promise,\n resolve: (_: unknown) => void,\n rawJob: RawJob\n ) => {\n if (this.isExecuterAvailable()) {\n await this.runExecuter(executer, resolve, rawJob);\n } else {\n this.queuedJobExecuter.push(this.runExecuter.bind(null, executer, resolve, rawJob));\n }\n };\n\n private runExecuter = async (\n executer: (rawJob: RawJob) => Promise,\n resolve: (_: unknown) => void,\n rawJob: RawJob\n ) => {\n try {\n await executer(rawJob);\n } finally {\n resolve(true);\n if (this.queuedJobExecuter.length > 0 && this.isExecuterAvailable()) {\n await this.queuedJobExecuter.shift()();\n }\n }\n };\n private isExecuterAvailable() {\n return this.concurrency <= 0 || this.activeJobCount < this.concurrency;\n }\n private isExecuting() {\n return this.activeJobCount > 0;\n }\n\n private finishQueue() {\n this.onQueueFinish(this.executedJobs);\n this.isActive = false;\n clearTimeout(this.timeoutId);\n }\n\n async getJobsForWorker(workerName: string) {\n const { isBusy, availableExecuters } = this.workers[workerName];\n if (!isBusy) {\n return await this.jobStore.getJobsForWorker(workerName, availableExecuters);\n } else {\n return await this.getJobsForAlternateWorker();\n }\n }\n\n async getJobsForWorkerWithDeleted(workerName: string) {\n const { isBusy, availableExecuters } = this.workers[workerName];\n if (!isBusy) {\n return await this.jobStore.getJobsForWorkerWithDeleted(workerName, availableExecuters);\n } else {\n return await this.getJobsForAlternateWorker();\n }\n }\n\n private async getJobsForAlternateWorker() {\n for (const workerName of Object.keys(this.workers)) {\n const { isBusy, availableExecuters } = this.workers[workerName];\n let nextJobs: RawJob[] = [];\n if (!isBusy) {\n nextJobs = await this.jobStore.getJobsForWorker(workerName, availableExecuters);\n }\n if (nextJobs.length > 0) {\n return nextJobs;\n }\n }\n return [];\n }\n\n private excuteJob = async (rawJob: RawJob) => {\n const worker = this.workers[rawJob.workerName];\n const payload = JSON.parse(rawJob.payload) as Worker;\n const job = { ...rawJob, ...{ payload } } as Job;\n\n try {\n job.status = \"processing\";\n this.jobStore.updateJob({ ...job, payload: JSON.stringify(payload) });\n this.emit('jobStarted', job);\n\n this.activeJobCount++;\n if (!this.workers[rawJob.workerName]) {\n throw new QueueError(`Missing worker with name ${rawJob.workerName}`, \"error\");\n }\n const promise = worker.execute(rawJob);\n\n this.runningJobPromises[rawJob.id] = promise;\n await promise;\n\n worker.triggerSuccess(job);\n job.status = \"finished\";\n this.jobStore.updateJob({ ...job, payload: JSON.stringify(payload) });\n this.jobStore.removeJob(rawJob);\n this.emit('jobSucceeded', job);\n } catch (err) {\n const error = err as QueueError;\n const { attempts } = rawJob;\n // eslint-disable-next-line prefer-const\n let { errors, failedAttempts } = JSON.parse(rawJob.metaData) as { errors: string[]; failedAttempts: number };\n failedAttempts++;\n let failed = '';\n if (failedAttempts >= attempts) {\n failed = new Date().toISOString();\n }\n const metaData = JSON.stringify({ errors: [...errors, error], failedAttempts });\n worker.triggerFailure({ ...job, metaData, failed }, error);\n const failedJob = { ...rawJob, ...{ active: FALSE, metaData, failed, status: error.code === \"cancelled\" ? \"cancelled\" : \"failed\" } } as RawJob;\n this.jobStore.updateJob(failedJob);\n this.emit('jobFailed', failedJob, error);\n } finally {\n delete this.runningJobPromises[job.id];\n worker.decreaseExecutionCount();\n worker.triggerCompletion(job);\n this.emit('jobCompleted', { ...job });\n this.executedJobs.push(rawJob);\n this.activeJobCount--;\n }\n };\n}\nexport default Queue.instance;\n"],"mappings":"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","ignoreList":[]} \ No newline at end of file diff --git a/lib/module/Queue.js b/lib/module/Queue.js index 7abeb6f..7b0e65e 100644 --- a/lib/module/Queue.js +++ b/lib/module/Queue.js @@ -94,7 +94,7 @@ export class Queue extends EventEmitter { return; } let nextJob = await this.jobStore.getWorkInProgressJob(); - if (!nextJob) { + if (!this.isJobNotEmpty(nextJob)) { nextJob = await this.jobStore.getNextJob(); } if (this.isJobNotEmpty(nextJob)) { diff --git a/lib/module/Queue.js.map b/lib/module/Queue.js.map index f19ba57..eb2b1cd 100644 --- a/lib/module/Queue.js.map +++ b/lib/module/Queue.js.map @@ -1 +1 @@ -{"version":3,"names":["AppState","NativeModules","Platform","FALSE","Uuid","CANCEL","EventEmitter","QueueError","Error","constructor","message","code","_defineProperty","name","Queue","instance","queueInstance","isRunning","isActive","registeredWorkers","workers","job","jobStore","updateJob","active","finishQueue","nextJob","getWorkInProgressJob","getNextJob","isJobNotEmpty","nextJobs","getJobsForWorker","workerName","processingJobs","map","limitExecution","excuteJob","Promise","all","isExecuting","scheduleQueue","executer","rawJob","resolve","enqueueJobExecuter","isExecuterAvailable","runExecuter","queuedJobExecuter","push","bind","length","shift","worker","payload","JSON","parse","status","stringify","emit","activeJobCount","promise","execute","runningJobPromises","id","triggerSuccess","removeJob","err","error","attempts","errors","failedAttempts","metaData","failed","Date","toISOString","triggerFailure","failedJob","decreaseExecutionCount","triggerCompletion","executedJobs","JobQueue","timeoutId","updateInterval","onQueueFinish","concurrency","getJobs","getJobsWithDeleted","removeJobPermanent","removeJobPermanently","requeueJob","newJob","start","then","console","log","catch","configure","options","addWorker","removeWorker","deleteRelatedJobs","removeJobsByWorkerName","addJob","timeout","priority","startQueue","v4","created","isDeleted","resetActiveJobs","stop","cancelJob","jobId","exception","undefined","warn","cancelAllActiveJobs","jobs","forEach","Boolean","cancelActiveJob","activeMarkedJobs","getActiveMarkedJobs","resetTasks","resetActiveJob","currentState","OS","setTimeout","runQueue","Object","keys","clearTimeout","isBusy","availableExecuters","getJobsForAlternateWorker","getJobsForWorkerWithDeleted","_Queue"],"sources":["Queue.ts"],"sourcesContent":["/* eslint-disable no-extra-boolean-cast */\n/* eslint-disable @typescript-eslint/no-empty-function */\nimport { AppState, NativeModules, Platform } from 'react-native';\n\nimport { FALSE, Job, RawJob, TRUE } from './models/Job';\nimport { JobStore } from './models/JobStore';\nimport { Uuid } from './utils/Uuid';\nimport { Worker, CANCEL, CancellablePromise } from './Worker';\n\n\nimport EventEmitter from 'eventemitter3';\n\ntype QueueErrorType = \"cancelled\" | \"error\";\n\nexport class QueueError extends Error {\n code: QueueErrorType;\n constructor(message: string, code: QueueErrorType = \"error\") {\n super(message);\n this.name = 'QueueError';\n this.code = code;\n }\n}\n\n/**\n * Events emitted by the Queue.\n */\nexport interface QueueEvents {\n /**\n * Fired when a worker is added.\n * @param workerName Name of the worker.\n */\n workerAdded: (workerName: string) => void;\n\n /**\n * Fired when a job is added to the queue.\n * @param job The RawJob that was added.\n */\n jobAdded: (job: RawJob) => void;\n\n /**\n * Fired when a job starts processing.\n * @param job The RawJob that started.\n */\n jobStarted: (job: RawJob) => void;\n\n /**\n * Fired when a job completes successfully.\n * @param job The Job with payload that succeeded.\n */\n jobSucceeded: (job: Job) => void;\n\n /**\n * Fired when a job fails.\n * @param job The RawJob that failed.\n * @param error The error thrown.\n */\n jobFailed: (job: RawJob, error: Error) => void;\n\n /**\n * Fired when a job fails.\n * @param job The RawJob that failed.\n * @param error The error thrown.\n */\n jobCancelled: (job: RawJob) => void;\n\n /**\n * Fired when a job completes (regardless of success or failure).\n * @param job The RawJob that finished.\n */\n jobCompleted: (job: RawJob) => void;\n\n /**\n * Fired when a job is deleted.\n * @param job The RawJob that was deleted.\n */\n jobDeleted: (job: RawJob) => void\n\n /**\n * Fired when a job is requeued.\n * @param job The RawJob that was requeued.\n */\n jobRequeued: (job: RawJob) => void\n}\n\n\n/**\n * Options to configure the queue\n */\nexport interface QueueOptions {\n /**\n * A callback function which is called after the queue has been stopped\n * @parameter executedJobs\n */\n onQueueFinish?: (executedJobs: Array>) => void;\n /**\n * Interval in which the queue checks for new jobs to execute\n */\n updateInterval?: number;\n concurrency?: number;\n}\n/**\n * ## Usage\n *\n * ```typescript\n * import queue from 'react-native-job-queue'\n *\n * queue.configure({onQueueFinish:(executedJobs:Job[])=>{\n * console.log(\"Queue stopped and executed\",executedJobs)\n * }});\n * queue.addWorker(new Worker(\"testWorker\",async(payload, id)=>{\n * return new Promise((resolve) => {\n * setTimeout(() => {\n * console.log('Executing jobId', id, 'with:', payload.text);\n * resolve();\n * }, payload.delay);});\n * }))\n * queue.addJob(\"testWorker\",{text:\"Job example payload content text\",delay:5000})\n * ```\n */\nexport class Queue extends EventEmitter {\n static get instance() {\n if (this.queueInstance) {\n return this.queueInstance;\n } else {\n this.queueInstance = new Queue();\n return this.queueInstance;\n }\n }\n /**\n * @returns true if the Queue is running and false otherwise\n */\n get isRunning() {\n return this.isActive;\n }\n /**\n * @returns the workers map (readonly)\n */\n get registeredWorkers() {\n return this.workers;\n }\n private static queueInstance: Queue | null;\n private emitter: EventEmitter = new EventEmitter();\n\n private jobStore: JobStore;\n private workers: { [key: string]: Worker };\n private isActive: boolean;\n\n private timeoutId: number;\n private executedJobs: Array>;\n private activeJobCount: number;\n\n private concurrency: number;\n private updateInterval: number;\n private onQueueFinish: (executedJobs: Array>) => void;\n\n private queuedJobExecuter: any[] = [];\n private runningJobPromises: { [key: string]: CancellablePromise };\n\n private constructor() {\n super();\n this.jobStore = NativeModules.JobQueue;\n this.workers = {};\n this.runningJobPromises = {};\n this.isActive = false;\n\n this.timeoutId = 0;\n this.executedJobs = [];\n this.activeJobCount = 0;\n\n this.updateInterval = 10;\n this.onQueueFinish = (executedJobs: Array>) => { };\n this.concurrency = -1;\n }\n\n\n\n /**\n * @returns a promise that resolves all jobs of jobStore\n */\n async getJobs() {\n return await this.jobStore.getJobs();\n }\n async getJobsWithDeleted() {\n return await this.jobStore.getJobsWithDeleted();\n }\n /**\n * @param job the job to be deleted\n */\n removeJob(job: RawJob) {\n this.jobStore.removeJob(job);\n this.emit(\"jobDeleted\", job)\n }\n removeJobPermanent(job: RawJob) {\n this.jobStore.removeJobPermanently(job);\n this.emit(\"jobDeleted\", job)\n }\n /**\n * @param job the job which should be requeued\n */\n requeueJob(job: RawJob) {\n const newJob = { ...job, failed: '', status: \"idle\", active: FALSE } as RawJob;\n this.jobStore.updateJob(newJob);\n this.emit(\"jobRequeued\", newJob)\n if (!this.isActive) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n this.start().then(() => {\n console.log(\"Queue restarted\")\n }).catch(() => {\n console.log(\"Queue could not be restarted\")\n });\n }\n }\n\n configure(options: QueueOptions) {\n const {\n onQueueFinish = (executedJobs: Array>) => { },\n updateInterval = 10,\n concurrency = -1,\n } = options;\n this.onQueueFinish = onQueueFinish;\n this.updateInterval = updateInterval;\n this.concurrency = concurrency;\n }\n /**\n * adds a [[Worker]] to the queue which can execute Jobs\n * @param worker\n */\n addWorker(worker: Worker) {\n if (this.workers[worker.name]) {\n throw new QueueError(`Worker \"${worker.name}\" already exists.`, \"error\");\n }\n this.workers[worker.name] = worker;\n this.emit('workerAdded', worker.name);\n }\n\n /**\n * removes worker from queue\n *\n * @param name\n * @param [deleteRelatedJobs=false] removes all queued jobs releated to the worker if set to true\n */\n removeWorker(name: string, deleteRelatedJobs = false) {\n delete this.workers[name];\n if (deleteRelatedJobs) {\n this.jobStore.removeJobsByWorkerName(name);\n }\n }\n\n /**\n * adds a job to the queue\n * @param workerName name of the worker which should be used to excute the job\n * @param [payload={}] payload which is passed as parameter to the executer\n * @param [options={ attempts: 0, timeout: 0, priority: 0 }] options to set max attempts, a timeout and a priority\n * @param [startQueue=true] if set to false the queue won't start automaticly when adding a job\n * @returns job id\n */\n addJob

(\n workerName: string,\n payload: P,\n options = { attempts: 0, timeout: 0, priority: 0 },\n startQueue = true\n ) {\n const { attempts = 0, timeout = 0, priority = 0 } = options;\n const id: string = Uuid.v4();\n const job: RawJob = {\n id,\n payload: JSON.stringify(payload || {}),\n metaData: JSON.stringify({ failedAttempts: 0, errors: [] }),\n active: FALSE,\n created: new Date().toISOString(),\n failed: '',\n workerName,\n attempts,\n timeout,\n priority,\n isDeleted: false,\n status: \"idle\"\n };\n if (!this.workers[job.workerName]) {\n throw new QueueError(`Missing worker with name ${job.workerName}`);\n }\n\n this.jobStore.addJob(job);\n this.emit('jobAdded', job);\n if (startQueue && !this.isActive) {\n this.start();\n }\n\n return id;\n }\n /**\n * starts the queue to execute queued jobs\n */\n async start() {\n if (!this.isActive) {\n this.isActive = true;\n this.executedJobs = [];\n await this.resetActiveJobs();\n this.scheduleQueue();\n }\n }\n /**\n * stop the queue from executing queued jobs\n */\n stop() {\n this.isActive = false;\n }\n\n /**\n * cancel running job\n */\n cancelJob(jobId: string, exception?: Error) {\n const promise = this.runningJobPromises[jobId];\n if (promise !== undefined && typeof promise[CANCEL] === 'function') {\n promise[CANCEL](exception || new QueueError(`job canceled`, \"cancelled\"));\n } else if (!promise[CANCEL]) {\n console.warn('Worker does not have a cancel method implemented');\n } else {\n throw new QueueError(`Job with id ${jobId} not currently running`, \"error\");\n }\n }\n async cancelAllActiveJobs() {\n const jobs = await this.jobStore.getJobs()\n\n jobs.forEach((job) => {\n const newJob = { ...job, ...{ active: FALSE, status: \"cancelled\" } };\n const isRunning = this.runningJobPromises[job.id];\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n if (!!Boolean(isRunning)) {\n this.cancelJob(job.id, new QueueError(`Job with id ${job.id} cancelled`, \"cancelled\"));\n }\n this.jobStore.updateJob(newJob as RawJob);\n this.emit('jobCancelled', newJob as RawJob);\n })\n }\n cancelActiveJob(job: RawJob) {\n const newJob = { ...job, ...{ active: FALSE, status: \"cancelled\" } };\n\n const isRunning = this.runningJobPromises[job.id];\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n if (!!isRunning) {\n this.cancelJob(job.id, new QueueError(`Job with id ${job.id} cancelled`, \"cancelled\"));\n }\n\n this.jobStore.updateJob(newJob as RawJob);\n\n this.emit('jobCancelled', newJob as RawJob);\n }\n\n private resetActiveJob = (job: RawJob) => {\n this.jobStore.updateJob({ ...job, ...{ active: FALSE } });\n };\n private async resetActiveJobs() {\n const activeMarkedJobs = await this.jobStore.getActiveMarkedJobs();\n const resetTasks = activeMarkedJobs.map(this.resetActiveJob);\n await Promise.all(resetTasks);\n }\n private scheduleQueue() {\n if (AppState.currentState === 'active' && Platform.OS === \"ios\") {\n this.timeoutId = setTimeout(this.runQueue, this.updateInterval);\n } else {\n this.runQueue();\n }\n }\n private runQueue = async () => {\n if (!this.isActive) {\n this.finishQueue();\n return;\n }\n let nextJob = await this.jobStore.getWorkInProgressJob();\n if (!nextJob) {\n nextJob = await this.jobStore.getNextJob();\n }\n if (this.isJobNotEmpty(nextJob)) {\n const nextJobs = await this.getJobsForWorker(nextJob.workerName);\n const processingJobs = nextJobs.map(async (job) => this.limitExecution(this.excuteJob, job));\n await Promise.all(processingJobs);\n } else if (!this.isExecuting()) {\n this.finishQueue();\n return;\n }\n this.scheduleQueue();\n };\n\n private isJobNotEmpty(rawJob: RawJob | {}) {\n return Object.keys(rawJob).length > 0;\n }\n\n private limitExecution = async (executer: (rawJob: RawJob) => Promise, rawJob: RawJob) => {\n return new Promise(async (resolve) => await this.enqueueJobExecuter(executer, resolve, rawJob));\n };\n\n private enqueueJobExecuter = async (\n executer: (rawJob: RawJob) => Promise,\n resolve: (_: unknown) => void,\n rawJob: RawJob\n ) => {\n if (this.isExecuterAvailable()) {\n await this.runExecuter(executer, resolve, rawJob);\n } else {\n this.queuedJobExecuter.push(this.runExecuter.bind(null, executer, resolve, rawJob));\n }\n };\n\n private runExecuter = async (\n executer: (rawJob: RawJob) => Promise,\n resolve: (_: unknown) => void,\n rawJob: RawJob\n ) => {\n try {\n await executer(rawJob);\n } finally {\n resolve(true);\n if (this.queuedJobExecuter.length > 0 && this.isExecuterAvailable()) {\n await this.queuedJobExecuter.shift()();\n }\n }\n };\n private isExecuterAvailable() {\n return this.concurrency <= 0 || this.activeJobCount < this.concurrency;\n }\n private isExecuting() {\n return this.activeJobCount > 0;\n }\n\n private finishQueue() {\n this.onQueueFinish(this.executedJobs);\n this.isActive = false;\n clearTimeout(this.timeoutId);\n }\n\n async getJobsForWorker(workerName: string) {\n const { isBusy, availableExecuters } = this.workers[workerName];\n if (!isBusy) {\n return await this.jobStore.getJobsForWorker(workerName, availableExecuters);\n } else {\n return await this.getJobsForAlternateWorker();\n }\n }\n\n async getJobsForWorkerWithDeleted(workerName: string) {\n const { isBusy, availableExecuters } = this.workers[workerName];\n if (!isBusy) {\n return await this.jobStore.getJobsForWorkerWithDeleted(workerName, availableExecuters);\n } else {\n return await this.getJobsForAlternateWorker();\n }\n }\n\n private async getJobsForAlternateWorker() {\n for (const workerName of Object.keys(this.workers)) {\n const { isBusy, availableExecuters } = this.workers[workerName];\n let nextJobs: RawJob[] = [];\n if (!isBusy) {\n nextJobs = await this.jobStore.getJobsForWorker(workerName, availableExecuters);\n }\n if (nextJobs.length > 0) {\n return nextJobs;\n }\n }\n return [];\n }\n\n private excuteJob = async (rawJob: RawJob) => {\n const worker = this.workers[rawJob.workerName];\n const payload = JSON.parse(rawJob.payload) as Worker;\n const job = { ...rawJob, ...{ payload } } as Job;\n\n try {\n job.status = \"processing\";\n this.jobStore.updateJob({ ...job, payload: JSON.stringify(payload) });\n this.emit('jobStarted', job);\n\n this.activeJobCount++;\n if (!this.workers[rawJob.workerName]) {\n throw new QueueError(`Missing worker with name ${rawJob.workerName}`, \"error\");\n }\n const promise = worker.execute(rawJob);\n\n this.runningJobPromises[rawJob.id] = promise;\n await promise;\n\n worker.triggerSuccess(job);\n job.status = \"finished\";\n this.jobStore.updateJob({ ...job, payload: JSON.stringify(payload) });\n this.jobStore.removeJob(rawJob);\n this.emit('jobSucceeded', job);\n } catch (err) {\n const error = err as QueueError;\n const { attempts } = rawJob;\n // eslint-disable-next-line prefer-const\n let { errors, failedAttempts } = JSON.parse(rawJob.metaData) as { errors: string[]; failedAttempts: number };\n failedAttempts++;\n let failed = '';\n if (failedAttempts >= attempts) {\n failed = new Date().toISOString();\n }\n const metaData = JSON.stringify({ errors: [...errors, error], failedAttempts });\n worker.triggerFailure({ ...job, metaData, failed }, error);\n const failedJob = { ...rawJob, ...{ active: FALSE, metaData, failed, status: error.code === \"cancelled\" ? \"cancelled\" : \"failed\" } } as RawJob;\n this.jobStore.updateJob(failedJob);\n this.emit('jobFailed', failedJob, error);\n } finally {\n delete this.runningJobPromises[job.id];\n worker.decreaseExecutionCount();\n worker.triggerCompletion(job);\n this.emit('jobCompleted', { ...job });\n this.executedJobs.push(rawJob);\n this.activeJobCount--;\n }\n };\n}\nexport default Queue.instance;\n"],"mappings":"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","ignoreList":[]} \ No newline at end of file +{"version":3,"names":["AppState","NativeModules","Platform","FALSE","Uuid","CANCEL","EventEmitter","QueueError","Error","constructor","message","code","_defineProperty","name","Queue","instance","queueInstance","isRunning","isActive","registeredWorkers","workers","job","jobStore","updateJob","active","finishQueue","nextJob","getWorkInProgressJob","isJobNotEmpty","getNextJob","nextJobs","getJobsForWorker","workerName","processingJobs","map","limitExecution","excuteJob","Promise","all","isExecuting","scheduleQueue","executer","rawJob","resolve","enqueueJobExecuter","isExecuterAvailable","runExecuter","queuedJobExecuter","push","bind","length","shift","worker","payload","JSON","parse","status","stringify","emit","activeJobCount","promise","execute","runningJobPromises","id","triggerSuccess","removeJob","err","error","attempts","errors","failedAttempts","metaData","failed","Date","toISOString","triggerFailure","failedJob","decreaseExecutionCount","triggerCompletion","executedJobs","JobQueue","timeoutId","updateInterval","onQueueFinish","concurrency","getJobs","getJobsWithDeleted","removeJobPermanent","removeJobPermanently","requeueJob","newJob","start","then","console","log","catch","configure","options","addWorker","removeWorker","deleteRelatedJobs","removeJobsByWorkerName","addJob","timeout","priority","startQueue","v4","created","isDeleted","resetActiveJobs","stop","cancelJob","jobId","exception","undefined","warn","cancelAllActiveJobs","jobs","forEach","Boolean","cancelActiveJob","activeMarkedJobs","getActiveMarkedJobs","resetTasks","resetActiveJob","currentState","OS","setTimeout","runQueue","Object","keys","clearTimeout","isBusy","availableExecuters","getJobsForAlternateWorker","getJobsForWorkerWithDeleted","_Queue"],"sources":["Queue.ts"],"sourcesContent":["/* eslint-disable no-extra-boolean-cast */\n/* eslint-disable @typescript-eslint/no-empty-function */\nimport { AppState, NativeModules, Platform } from 'react-native';\n\nimport { FALSE, Job, RawJob, TRUE } from './models/Job';\nimport { JobStore } from './models/JobStore';\nimport { Uuid } from './utils/Uuid';\nimport { Worker, CANCEL, CancellablePromise } from './Worker';\n\n\nimport EventEmitter from 'eventemitter3';\n\ntype QueueErrorType = \"cancelled\" | \"error\";\n\nexport class QueueError extends Error {\n code: QueueErrorType;\n constructor(message: string, code: QueueErrorType = \"error\") {\n super(message);\n this.name = 'QueueError';\n this.code = code;\n }\n}\n\n/**\n * Events emitted by the Queue.\n */\nexport interface QueueEvents {\n /**\n * Fired when a worker is added.\n * @param workerName Name of the worker.\n */\n workerAdded: (workerName: string) => void;\n\n /**\n * Fired when a job is added to the queue.\n * @param job The RawJob that was added.\n */\n jobAdded: (job: RawJob) => void;\n\n /**\n * Fired when a job starts processing.\n * @param job The RawJob that started.\n */\n jobStarted: (job: RawJob) => void;\n\n /**\n * Fired when a job completes successfully.\n * @param job The Job with payload that succeeded.\n */\n jobSucceeded: (job: Job) => void;\n\n /**\n * Fired when a job fails.\n * @param job The RawJob that failed.\n * @param error The error thrown.\n */\n jobFailed: (job: RawJob, error: Error) => void;\n\n /**\n * Fired when a job fails.\n * @param job The RawJob that failed.\n * @param error The error thrown.\n */\n jobCancelled: (job: RawJob) => void;\n\n /**\n * Fired when a job completes (regardless of success or failure).\n * @param job The RawJob that finished.\n */\n jobCompleted: (job: RawJob) => void;\n\n /**\n * Fired when a job is deleted.\n * @param job The RawJob that was deleted.\n */\n jobDeleted: (job: RawJob) => void\n\n /**\n * Fired when a job is requeued.\n * @param job The RawJob that was requeued.\n */\n jobRequeued: (job: RawJob) => void\n}\n\n\n/**\n * Options to configure the queue\n */\nexport interface QueueOptions {\n /**\n * A callback function which is called after the queue has been stopped\n * @parameter executedJobs\n */\n onQueueFinish?: (executedJobs: Array>) => void;\n /**\n * Interval in which the queue checks for new jobs to execute\n */\n updateInterval?: number;\n concurrency?: number;\n}\n/**\n * ## Usage\n *\n * ```typescript\n * import queue from 'react-native-job-queue'\n *\n * queue.configure({onQueueFinish:(executedJobs:Job[])=>{\n * console.log(\"Queue stopped and executed\",executedJobs)\n * }});\n * queue.addWorker(new Worker(\"testWorker\",async(payload, id)=>{\n * return new Promise((resolve) => {\n * setTimeout(() => {\n * console.log('Executing jobId', id, 'with:', payload.text);\n * resolve();\n * }, payload.delay);});\n * }))\n * queue.addJob(\"testWorker\",{text:\"Job example payload content text\",delay:5000})\n * ```\n */\nexport class Queue extends EventEmitter {\n static get instance() {\n if (this.queueInstance) {\n return this.queueInstance;\n } else {\n this.queueInstance = new Queue();\n return this.queueInstance;\n }\n }\n /**\n * @returns true if the Queue is running and false otherwise\n */\n get isRunning() {\n return this.isActive;\n }\n /**\n * @returns the workers map (readonly)\n */\n get registeredWorkers() {\n return this.workers;\n }\n private static queueInstance: Queue | null;\n private emitter: EventEmitter = new EventEmitter();\n\n private jobStore: JobStore;\n private workers: { [key: string]: Worker };\n private isActive: boolean;\n\n private timeoutId: number;\n private executedJobs: Array>;\n private activeJobCount: number;\n\n private concurrency: number;\n private updateInterval: number;\n private onQueueFinish: (executedJobs: Array>) => void;\n\n private queuedJobExecuter: any[] = [];\n private runningJobPromises: { [key: string]: CancellablePromise };\n\n private constructor() {\n super();\n this.jobStore = NativeModules.JobQueue;\n this.workers = {};\n this.runningJobPromises = {};\n this.isActive = false;\n\n this.timeoutId = 0;\n this.executedJobs = [];\n this.activeJobCount = 0;\n\n this.updateInterval = 10;\n this.onQueueFinish = (executedJobs: Array>) => { };\n this.concurrency = -1;\n }\n\n\n\n /**\n * @returns a promise that resolves all jobs of jobStore\n */\n async getJobs() {\n return await this.jobStore.getJobs();\n }\n async getJobsWithDeleted() {\n return await this.jobStore.getJobsWithDeleted();\n }\n /**\n * @param job the job to be deleted\n */\n removeJob(job: RawJob) {\n this.jobStore.removeJob(job);\n this.emit(\"jobDeleted\", job)\n }\n removeJobPermanent(job: RawJob) {\n this.jobStore.removeJobPermanently(job);\n this.emit(\"jobDeleted\", job)\n }\n /**\n * @param job the job which should be requeued\n */\n requeueJob(job: RawJob) {\n const newJob = { ...job, failed: '', status: \"idle\", active: FALSE } as RawJob;\n this.jobStore.updateJob(newJob);\n this.emit(\"jobRequeued\", newJob)\n if (!this.isActive) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n this.start().then(() => {\n console.log(\"Queue restarted\")\n }).catch(() => {\n console.log(\"Queue could not be restarted\")\n });\n }\n }\n\n configure(options: QueueOptions) {\n const {\n onQueueFinish = (executedJobs: Array>) => { },\n updateInterval = 10,\n concurrency = -1,\n } = options;\n this.onQueueFinish = onQueueFinish;\n this.updateInterval = updateInterval;\n this.concurrency = concurrency;\n }\n /**\n * adds a [[Worker]] to the queue which can execute Jobs\n * @param worker\n */\n addWorker(worker: Worker) {\n if (this.workers[worker.name]) {\n throw new QueueError(`Worker \"${worker.name}\" already exists.`, \"error\");\n }\n this.workers[worker.name] = worker;\n this.emit('workerAdded', worker.name);\n }\n\n /**\n * removes worker from queue\n *\n * @param name\n * @param [deleteRelatedJobs=false] removes all queued jobs releated to the worker if set to true\n */\n removeWorker(name: string, deleteRelatedJobs = false) {\n delete this.workers[name];\n if (deleteRelatedJobs) {\n this.jobStore.removeJobsByWorkerName(name);\n }\n }\n\n /**\n * adds a job to the queue\n * @param workerName name of the worker which should be used to excute the job\n * @param [payload={}] payload which is passed as parameter to the executer\n * @param [options={ attempts: 0, timeout: 0, priority: 0 }] options to set max attempts, a timeout and a priority\n * @param [startQueue=true] if set to false the queue won't start automaticly when adding a job\n * @returns job id\n */\n addJob

(\n workerName: string,\n payload: P,\n options = { attempts: 0, timeout: 0, priority: 0 },\n startQueue = true\n ) {\n const { attempts = 0, timeout = 0, priority = 0 } = options;\n const id: string = Uuid.v4();\n const job: RawJob = {\n id,\n payload: JSON.stringify(payload || {}),\n metaData: JSON.stringify({ failedAttempts: 0, errors: [] }),\n active: FALSE,\n created: new Date().toISOString(),\n failed: '',\n workerName,\n attempts,\n timeout,\n priority,\n isDeleted: false,\n status: \"idle\"\n };\n if (!this.workers[job.workerName]) {\n throw new QueueError(`Missing worker with name ${job.workerName}`);\n }\n\n this.jobStore.addJob(job);\n this.emit('jobAdded', job);\n if (startQueue && !this.isActive) {\n this.start();\n }\n\n return id;\n }\n /**\n * starts the queue to execute queued jobs\n */\n async start() {\n if (!this.isActive) {\n this.isActive = true;\n this.executedJobs = [];\n await this.resetActiveJobs();\n this.scheduleQueue();\n }\n }\n /**\n * stop the queue from executing queued jobs\n */\n stop() {\n this.isActive = false;\n }\n\n /**\n * cancel running job\n */\n cancelJob(jobId: string, exception?: Error) {\n const promise = this.runningJobPromises[jobId];\n if (promise !== undefined && typeof promise[CANCEL] === 'function') {\n promise[CANCEL](exception || new QueueError(`job canceled`, \"cancelled\"));\n } else if (!promise[CANCEL]) {\n console.warn('Worker does not have a cancel method implemented');\n } else {\n throw new QueueError(`Job with id ${jobId} not currently running`, \"error\");\n }\n }\n async cancelAllActiveJobs() {\n const jobs = await this.jobStore.getJobs()\n\n jobs.forEach((job) => {\n const newJob = { ...job, ...{ active: FALSE, status: \"cancelled\" } };\n const isRunning = this.runningJobPromises[job.id];\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n if (!!Boolean(isRunning)) {\n this.cancelJob(job.id, new QueueError(`Job with id ${job.id} cancelled`, \"cancelled\"));\n }\n this.jobStore.updateJob(newJob as RawJob);\n this.emit('jobCancelled', newJob as RawJob);\n })\n }\n cancelActiveJob(job: RawJob) {\n const newJob = { ...job, ...{ active: FALSE, status: \"cancelled\" } };\n\n const isRunning = this.runningJobPromises[job.id];\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n if (!!isRunning) {\n this.cancelJob(job.id, new QueueError(`Job with id ${job.id} cancelled`, \"cancelled\"));\n }\n\n this.jobStore.updateJob(newJob as RawJob);\n\n this.emit('jobCancelled', newJob as RawJob);\n }\n\n private resetActiveJob = (job: RawJob) => {\n this.jobStore.updateJob({ ...job, ...{ active: FALSE } });\n };\n private async resetActiveJobs() {\n const activeMarkedJobs = await this.jobStore.getActiveMarkedJobs();\n const resetTasks = activeMarkedJobs.map(this.resetActiveJob);\n await Promise.all(resetTasks);\n }\n private scheduleQueue() {\n if (AppState.currentState === 'active' && Platform.OS === \"ios\") {\n this.timeoutId = setTimeout(this.runQueue, this.updateInterval);\n } else {\n this.runQueue();\n }\n }\n private runQueue = async () => {\n if (!this.isActive) {\n this.finishQueue();\n return;\n }\n let nextJob = await this.jobStore.getWorkInProgressJob();\n if (!this.isJobNotEmpty(nextJob)) {\n nextJob = await this.jobStore.getNextJob();\n }\n if (this.isJobNotEmpty(nextJob)) {\n const nextJobs = await this.getJobsForWorker(nextJob.workerName);\n const processingJobs = nextJobs.map(async (job) => this.limitExecution(this.excuteJob, job));\n await Promise.all(processingJobs);\n } else if (!this.isExecuting()) {\n this.finishQueue();\n return;\n }\n this.scheduleQueue();\n };\n\n private isJobNotEmpty(rawJob: RawJob | {}) {\n return Object.keys(rawJob).length > 0;\n }\n\n private limitExecution = async (executer: (rawJob: RawJob) => Promise, rawJob: RawJob) => {\n return new Promise(async (resolve) => await this.enqueueJobExecuter(executer, resolve, rawJob));\n };\n\n private enqueueJobExecuter = async (\n executer: (rawJob: RawJob) => Promise,\n resolve: (_: unknown) => void,\n rawJob: RawJob\n ) => {\n if (this.isExecuterAvailable()) {\n await this.runExecuter(executer, resolve, rawJob);\n } else {\n this.queuedJobExecuter.push(this.runExecuter.bind(null, executer, resolve, rawJob));\n }\n };\n\n private runExecuter = async (\n executer: (rawJob: RawJob) => Promise,\n resolve: (_: unknown) => void,\n rawJob: RawJob\n ) => {\n try {\n await executer(rawJob);\n } finally {\n resolve(true);\n if (this.queuedJobExecuter.length > 0 && this.isExecuterAvailable()) {\n await this.queuedJobExecuter.shift()();\n }\n }\n };\n private isExecuterAvailable() {\n return this.concurrency <= 0 || this.activeJobCount < this.concurrency;\n }\n private isExecuting() {\n return this.activeJobCount > 0;\n }\n\n private finishQueue() {\n this.onQueueFinish(this.executedJobs);\n this.isActive = false;\n clearTimeout(this.timeoutId);\n }\n\n async getJobsForWorker(workerName: string) {\n const { isBusy, availableExecuters } = this.workers[workerName];\n if (!isBusy) {\n return await this.jobStore.getJobsForWorker(workerName, availableExecuters);\n } else {\n return await this.getJobsForAlternateWorker();\n }\n }\n\n async getJobsForWorkerWithDeleted(workerName: string) {\n const { isBusy, availableExecuters } = this.workers[workerName];\n if (!isBusy) {\n return await this.jobStore.getJobsForWorkerWithDeleted(workerName, availableExecuters);\n } else {\n return await this.getJobsForAlternateWorker();\n }\n }\n\n private async getJobsForAlternateWorker() {\n for (const workerName of Object.keys(this.workers)) {\n const { isBusy, availableExecuters } = this.workers[workerName];\n let nextJobs: RawJob[] = [];\n if (!isBusy) {\n nextJobs = await this.jobStore.getJobsForWorker(workerName, availableExecuters);\n }\n if (nextJobs.length > 0) {\n return nextJobs;\n }\n }\n return [];\n }\n\n private excuteJob = async (rawJob: RawJob) => {\n const worker = this.workers[rawJob.workerName];\n const payload = JSON.parse(rawJob.payload) as Worker;\n const job = { ...rawJob, ...{ payload } } as Job;\n\n try {\n job.status = \"processing\";\n this.jobStore.updateJob({ ...job, payload: JSON.stringify(payload) });\n this.emit('jobStarted', job);\n\n this.activeJobCount++;\n if (!this.workers[rawJob.workerName]) {\n throw new QueueError(`Missing worker with name ${rawJob.workerName}`, \"error\");\n }\n const promise = worker.execute(rawJob);\n\n this.runningJobPromises[rawJob.id] = promise;\n await promise;\n\n worker.triggerSuccess(job);\n job.status = \"finished\";\n this.jobStore.updateJob({ ...job, payload: JSON.stringify(payload) });\n this.jobStore.removeJob(rawJob);\n this.emit('jobSucceeded', job);\n } catch (err) {\n const error = err as QueueError;\n const { attempts } = rawJob;\n // eslint-disable-next-line prefer-const\n let { errors, failedAttempts } = JSON.parse(rawJob.metaData) as { errors: string[]; failedAttempts: number };\n failedAttempts++;\n let failed = '';\n if (failedAttempts >= attempts) {\n failed = new Date().toISOString();\n }\n const metaData = JSON.stringify({ errors: [...errors, error], failedAttempts });\n worker.triggerFailure({ ...job, metaData, failed }, error);\n const failedJob = { ...rawJob, ...{ active: FALSE, metaData, failed, status: error.code === \"cancelled\" ? \"cancelled\" : \"failed\" } } as RawJob;\n this.jobStore.updateJob(failedJob);\n this.emit('jobFailed', failedJob, error);\n } finally {\n delete this.runningJobPromises[job.id];\n worker.decreaseExecutionCount();\n worker.triggerCompletion(job);\n this.emit('jobCompleted', { ...job });\n this.executedJobs.push(rawJob);\n this.activeJobCount--;\n }\n };\n}\nexport default Queue.instance;\n"],"mappings":"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","ignoreList":[]} \ No newline at end of file diff --git a/package.json b/package.json index 6865c3a..2742196 100644 --- a/package.json +++ b/package.json @@ -47,9 +47,11 @@ "react-native": ">=0.57.0-rc.0 <1.0.x" }, "dependencies": { + "@nozbe/watermelondb": "^0.28.0", "eventemitter3": "^5.0.1" }, "devDependencies": { + "@babel/plugin-proposal-decorators": "^7.27.1", "@react-native-community/bob": "^0.17.1", "@types/jest": "^24.0.17", "@types/react": "^16.8.25", @@ -75,4 +77,4 @@ "typescript" ] } -} \ No newline at end of file +} diff --git a/react-native-job-queue.podspec b/react-native-job-queue.podspec index e6ff768..fd3c670 100644 --- a/react-native-job-queue.podspec +++ b/react-native-job-queue.podspec @@ -17,10 +17,11 @@ Pod::Spec.new do |s| s.source = { :git => "https://github.com/SimonErm/react-native-job-queue.git", :tag => "#{s.version}" } s.swift_version = "5.0" - s.source_files = "ios/**/*.{h,m,swift}" + # No longer providing its own native iOS source files directly in this package + # s.source_files = "ios/**/*.{h,m,swift}" s.requires_arc = true s.dependency "React" - s.library = "sqlite3" + # s.library = "sqlite3" # Removed as the native SQLite code is deleted # s.dependency "..." end diff --git a/src/JobStore.ts b/src/JobStore.ts new file mode 100644 index 0000000..b2c6354 --- /dev/null +++ b/src/JobStore.ts @@ -0,0 +1,217 @@ +import { Platform } from 'react-native'; +import { Database, Model, Q, Collection } from '@nozbe/watermelondb'; +import { field, table } from '@nozbe/watermelondb/decorators'; + +import { database, JobModel } from './watermelon/database'; +import { JobStore as JobStoreInterface } from './models/JobStore'; +import { RawJob, JobStatus, Bool, TRUE, FALSE } from './models/Job'; // Assuming TRUE/FALSE are 0/1 + +// Helper function to map JobModel to RawJob +function mapJobModelToRawJob(jobModel: JobModel): RawJob { + if (!jobModel) { + return {} as RawJob; // Or handle as an error/null based on how getNextJob/getWorkInProgressJob expect it + } + return { + id: jobModel.id, // WatermelonDB model ID + workerName: jobModel.workerName, + active: jobModel.active ? TRUE : FALSE, + payload: jobModel.payload, + metaData: jobModel.metaData, + attempts: jobModel.attempts, + created: jobModel.created, // Ensure this matches RawJob's expected format + status: jobModel.status as JobStatus, + failed: jobModel.failed || '', // RawJob expects string, model might have null + timeout: jobModel.timeout, + priority: jobModel.priority, + isDeleted: jobModel.isDeleted, // RawJob has isDeleted: boolean + }; +} + +function mapRawJobToJobModelFields(job: RawJob, record: JobModel) { + // Note: record.id is managed by WatermelonDB or set via record._raw.id if needed + // For creation, some fields like 'id' might be handled differently + if (job.id && record._raw) { // only for creation. On update, id is not changed. + record._raw.id = job.id; + } + record.workerName = job.workerName; + record.active = job.active === TRUE; + record.payload = job.payload; + record.metaData = job.metaData; + record.attempts = job.attempts; + record.created = job.created; + record.status = job.status; + record.failed = job.failed; + record.timeout = job.timeout; + record.priority = job.priority; + record.isDeleted = job.isDeleted; // Assuming RawJob.isDeleted is boolean +} + + +export class WatermelonDBJobStore implements JobStoreInterface { + private get jobsCollection(): Collection { + return database.collections.get('jobs'); + } + + async addJob(job: RawJob): Promise { + await database.write(async () => { + await this.jobsCollection.create(record => { + // WatermelonDB handles ID generation by default if job.id is not pre-set + // If job.id is meant to be external, it needs to be set via record._raw.id = job.id; + // For this implementation, let's assume job.id is provided and should be used. + if (!job.id) { + // This should ideally not happen if RawJob mandates an id. + // Or, we let WatermelonDB generate it (remove the line below) + throw new Error("Job ID must be provided when adding a job."); + } + record._raw.id = job.id; // Explicitly set the ID from RawJob + mapRawJobToJobModelFields(job, record); + }); + }); + } + + async getJobs(): Promise { + const jobModels = await this.jobsCollection.query(Q.where('is_deleted', false)).fetch(); + return jobModels.map(mapJobModelToRawJob); + } + + async getJobsWithDeleted(): Promise { + const jobModels = await this.jobsCollection.query().fetch(); + return jobModels.map(mapJobModelToRawJob); + } + + async getActiveMarkedJobs(): Promise { + const jobModels = await this.jobsCollection.query( + Q.and( + Q.where('active', true), + Q.where('is_deleted', false) + ) + ).fetch(); + return jobModels.map(mapJobModelToRawJob); + } + + async getNextJob(): Promise { + const result = await this.jobsCollection.query( + Q.where('is_deleted', false), + Q.where('active', false), + Q.where('failed', null), // Assumes 'failed' is null for non-failed, not empty string + Q.where('status', JobStatus.IDLE), // Use JobStatus enum + Q.sortBy('priority', Q.desc), + Q.sortBy('created', Q.asc), + Q.take(1) + ).fetch(); + + if (result.length > 0) { + return mapJobModelToRawJob(result[0]); + } + return {} as RawJob; // As per instruction for empty object + } + + async getWorkInProgressJob(): Promise { + const result = await this.jobsCollection.query( + Q.where('is_deleted', false), + Q.where('active', true), + Q.where('status', JobStatus.PROCESSING), // Use JobStatus enum + Q.sortBy('created', Q.asc), + Q.take(1) + ).fetch(); + + if (result.length > 0) { + return mapJobModelToRawJob(result[0]); + } + return {} as RawJob; // As per instruction for empty object + } + + async getJobsForWorker(name: string, count: number): Promise { + const jobModels = await this.jobsCollection.query( + Q.where('worker_name', name), + Q.where('is_deleted', false), + Q.where('active', false), + Q.where('status', JobStatus.IDLE), + Q.where('failed', null), + Q.sortBy('priority', Q.desc), + Q.sortBy('created', Q.asc), + Q.take(count) + ).fetch(); + return jobModels.map(mapJobModelToRawJob); + } + + async getJobsForWorkerWithDeleted(name: string, count: number): Promise { + // The requirement "active is false, status is 'idle', failed is empty or null" might be too restrictive + // if we want to see ALL jobs for a worker, including processed, failed etc. + // Assuming the requirement is strict as written: + const jobModels = await this.jobsCollection.query( + Q.where('worker_name', name), + // Q.where('active', false), // Removed as per "with deleted" implies less filtering + // Q.where('status', JobStatus.IDLE), // Removed + // Q.where('failed', null), // Removed + Q.sortBy('priority', Q.desc), // This sorting might not make sense for already processed/deleted jobs + Q.sortBy('created', Q.asc), + Q.take(count) + ).fetch(); + return jobModels.map(mapJobModelToRawJob); + } + + async updateJob(job: RawJob): Promise { + if (!job.id) { + throw new Error("Job ID must be provided for update."); + } + await database.write(async () => { + const jobRecord = await this.jobsCollection.find(job.id); + await jobRecord.update(record => { + mapRawJobToJobModelFields(job, record); + }); + }); + } + + async removeJob(job: RawJob): Promise { + if (!job.id) { + throw new Error("Job ID must be provided for soft delete."); + } + await database.write(async () => { + const jobRecord = await this.jobsCollection.find(job.id); + await jobRecord.update(record => { + record.isDeleted = true; + record.active = false; // Also mark as inactive + }); + }); + } + + async removeJobPermanently(job: RawJob): Promise { + if (!job.id) { + throw new Error("Job ID must be provided for permanent delete."); + } + await database.write(async () => { + const jobRecord = await this.jobsCollection.find(job.id); + await jobRecord.destroyPermanently(); + }); + } + + async removeJobsByWorkerName(workerName: string): Promise { + const jobsToMark = await this.jobsCollection.query( + Q.where('worker_name', workerName), + Q.where('is_deleted', false) // Only soft-delete those not already soft-deleted + ).fetch(); + + if (jobsToMark.length > 0) { + await database.write(async () => { + for (const job of jobsToMark) { + await job.update(j => { + j.isDeleted = true; + j.active = false; + }); + } + }); + } + } + + async deleteAllJobs(): Promise { + await database.write(async () => { + // Fetch all job records + const allJobs = await this.jobsCollection.query().fetch(); + // Create a batch of delete operations + const deletions = allJobs.map(job => job.prepareDestroyPermanently()); + // Execute the batch operation + await database.batch(...deletions); + }); + } +} diff --git a/src/Queue.ts b/src/Queue.ts index eeb1bec..08b156a 100644 --- a/src/Queue.ts +++ b/src/Queue.ts @@ -1,9 +1,10 @@ /* eslint-disable no-extra-boolean-cast */ /* eslint-disable @typescript-eslint/no-empty-function */ -import { AppState, NativeModules, Platform } from 'react-native'; +import { AppState, Platform } from 'react-native'; import { FALSE, Job, RawJob, TRUE } from './models/Job'; -import { JobStore } from './models/JobStore'; +import { JobStore } from './models/JobStore'; // This is the interface +import { WatermelonDBJobStore } from './JobStore'; // This is the implementation import { Uuid } from './utils/Uuid'; import { Worker, CANCEL, CancellablePromise } from './Worker'; @@ -141,7 +142,7 @@ export class Queue extends EventEmitter { private static queueInstance: Queue | null; private emitter: EventEmitter = new EventEmitter(); - private jobStore: JobStore; + private jobStore: JobStore; // Keep type as interface for flexibility private workers: { [key: string]: Worker }; private isActive: boolean; @@ -158,7 +159,7 @@ export class Queue extends EventEmitter { private constructor() { super(); - this.jobStore = NativeModules.JobQueue; + this.jobStore = new WatermelonDBJobStore(); this.workers = {}; this.runningJobPromises = {}; this.isActive = false; @@ -186,20 +187,20 @@ export class Queue extends EventEmitter { /** * @param job the job to be deleted */ - removeJob(job: RawJob) { - this.jobStore.removeJob(job); + async removeJob(job: RawJob) { + await this.jobStore.removeJob(job); this.emit("jobDeleted", job) } - removeJobPermanent(job: RawJob) { - this.jobStore.removeJobPermanently(job); + async removeJobPermanent(job: RawJob) { + await this.jobStore.removeJobPermanently(job); this.emit("jobDeleted", job) } /** * @param job the job which should be requeued */ - requeueJob(job: RawJob) { + async requeueJob(job: RawJob) { const newJob = { ...job, failed: '', status: "idle", active: FALSE } as RawJob; - this.jobStore.updateJob(newJob); + await this.jobStore.updateJob(newJob); this.emit("jobRequeued", newJob) if (!this.isActive) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment @@ -240,10 +241,10 @@ export class Queue extends EventEmitter { * @param name * @param [deleteRelatedJobs=false] removes all queued jobs releated to the worker if set to true */ - removeWorker(name: string, deleteRelatedJobs = false) { + async removeWorker(name: string, deleteRelatedJobs = false) { delete this.workers[name]; if (deleteRelatedJobs) { - this.jobStore.removeJobsByWorkerName(name); + await this.jobStore.removeJobsByWorkerName(name); } } @@ -255,7 +256,7 @@ export class Queue extends EventEmitter { * @param [startQueue=true] if set to false the queue won't start automaticly when adding a job * @returns job id */ - addJob

( + async addJob

( workerName: string, payload: P, options = { attempts: 0, timeout: 0, priority: 0 }, @@ -281,10 +282,11 @@ export class Queue extends EventEmitter { throw new QueueError(`Missing worker with name ${job.workerName}`); } - this.jobStore.addJob(job); + await this.jobStore.addJob(job); this.emit('jobAdded', job); if (startQueue && !this.isActive) { - this.start(); + // this.start() is already async + await this.start(); } return id; @@ -321,39 +323,38 @@ export class Queue extends EventEmitter { } } async cancelAllActiveJobs() { - const jobs = await this.jobStore.getJobs() + const jobs = await this.jobStore.getJobs(); // Already async - jobs.forEach((job) => { + for (const job of jobs) { // Use for...of for async operations in loop const newJob = { ...job, ...{ active: FALSE, status: "cancelled" } }; const isRunning = this.runningJobPromises[job.id]; - // eslint-disable-next-line @typescript-eslint/no-misused-promises if (!!Boolean(isRunning)) { this.cancelJob(job.id, new QueueError(`Job with id ${job.id} cancelled`, "cancelled")); } - this.jobStore.updateJob(newJob as RawJob); + await this.jobStore.updateJob(newJob as RawJob); // Added await this.emit('jobCancelled', newJob as RawJob); - }) + } } - cancelActiveJob(job: RawJob) { + async cancelActiveJob(job: RawJob) { // Made async const newJob = { ...job, ...{ active: FALSE, status: "cancelled" } }; const isRunning = this.runningJobPromises[job.id]; - // eslint-disable-next-line @typescript-eslint/no-misused-promises - if (!!isRunning) { + if (!!Boolean(isRunning)) { this.cancelJob(job.id, new QueueError(`Job with id ${job.id} cancelled`, "cancelled")); } - this.jobStore.updateJob(newJob as RawJob); + await this.jobStore.updateJob(newJob as RawJob); // Added await this.emit('jobCancelled', newJob as RawJob); } - private resetActiveJob = (job: RawJob) => { - this.jobStore.updateJob({ ...job, ...{ active: FALSE } }); + private resetActiveJob = async (job: RawJob) => { // Made async + await this.jobStore.updateJob({ ...job, ...{ active: FALSE } }); // Added await }; private async resetActiveJobs() { const activeMarkedJobs = await this.jobStore.getActiveMarkedJobs(); - const resetTasks = activeMarkedJobs.map(this.resetActiveJob); + // .map with async function returns array of Promises + const resetTasks = activeMarkedJobs.map(j => this.resetActiveJob(j)); // Pass the async function directly await Promise.all(resetTasks); } private scheduleQueue() { @@ -469,7 +470,8 @@ export class Queue extends EventEmitter { try { job.status = "processing"; - this.jobStore.updateJob({ ...job, payload: JSON.stringify(payload) }); + // Ensure payload is stringified for updateJob + await this.jobStore.updateJob({ ...job, payload: JSON.stringify(job.payload) }); // Added await this.emit('jobStarted', job); this.activeJobCount++; @@ -483,8 +485,8 @@ export class Queue extends EventEmitter { worker.triggerSuccess(job); job.status = "finished"; - this.jobStore.updateJob({ ...job, payload: JSON.stringify(payload) }); - this.jobStore.removeJob(rawJob); + await this.jobStore.updateJob({ ...job, payload: JSON.stringify(job.payload) }); // Added await + await this.jobStore.removeJob(rawJob); // This is a soft delete, added await this.emit('jobSucceeded', job); } catch (err) { const error = err as QueueError; @@ -499,7 +501,7 @@ export class Queue extends EventEmitter { const metaData = JSON.stringify({ errors: [...errors, error], failedAttempts }); worker.triggerFailure({ ...job, metaData, failed }, error); const failedJob = { ...rawJob, ...{ active: FALSE, metaData, failed, status: error.code === "cancelled" ? "cancelled" : "failed" } } as RawJob; - this.jobStore.updateJob(failedJob); + await this.jobStore.updateJob(failedJob); // Added await this.emit('jobFailed', failedJob, error); } finally { delete this.runningJobPromises[job.id]; diff --git a/src/watermelon/database.ts b/src/watermelon/database.ts new file mode 100644 index 0000000..4678d0b --- /dev/null +++ b/src/watermelon/database.ts @@ -0,0 +1,47 @@ +import { Platform } from 'react-native'; +import { Database, Model } from '@nozbe/watermelondb'; +import SQLiteAdapter from '@nozbe/watermelondb/adapters/sqlite'; +import { field, table } from '@nozbe/watermelondb/decorators'; + +import { myAppSchema } from './schema'; + +// Define the JobModel +@table('jobs') +export class JobModel extends Model { + static table = 'jobs'; // WatermelonDB static table name + + @field('worker_name') workerName!: string; + @field('active') active!: boolean; + @field('payload') payload!: string; + @field('meta_data') metaData!: string; + @field('attempts') attempts!: number; + @field('created') created!: string; // Consider number for actual timestamp storage + @field('status') status!: string; + @field('failed') failed?: string | null; // Optional field + @field('timeout') timeout!: number; + @field('priority') priority!: number; + @field('is_deleted') isDeleted!: boolean; +} + +// Configure the adapter +const adapter = new SQLiteAdapter({ + schema: myAppSchema, + jsi: Platform.OS === 'ios', // JSI is only available on iOS in some RN versions, might need to check compatibility or use false for broader compatibility initially + dbName: 'JobQueue', + onSetUpError: error => { + // It's crucial to handle database setup errors + // For example, log to a monitoring service or display an alert + console.error("Failed to set up WatermelonDB:", error); + // Depending on the app, you might want to throw the error, + // or attempt a recovery/reset, or inform the user. + }, +}); + +// Create and export the database instance +export const database = new Database({ + adapter, + modelClasses: [ + JobModel, + // Add other models here if you have more + ], +}); diff --git a/src/watermelon/schema.ts b/src/watermelon/schema.ts new file mode 100644 index 0000000..d808f82 --- /dev/null +++ b/src/watermelon/schema.ts @@ -0,0 +1,24 @@ +import { appSchema, tableSchema } from '@nozbe/watermelondb/Schema'; + +export const myAppSchema = appSchema({ + version: 1, + tables: [ + tableSchema({ + name: 'jobs', + columns: [ + { name: 'id', type: 'string', isOptional: false }, // id is the default primary key and should not be indexed here as per WatermelonDB docs for `id` + { name: 'worker_name', type: 'string', isOptional: false, isIndexed: true }, + { name: 'active', type: 'boolean', isOptional: false }, + { name: 'payload', type: 'string', isOptional: false }, + { name: 'meta_data', type: 'string', isOptional: false }, + { name: 'attempts', type: 'number', isOptional: false }, + { name: 'created', type: 'string', isOptional: false }, // WatermelonDB uses number for dates (timestamps) + { name: 'status', type: 'string', isOptional: false }, + { name: 'failed', type: 'string', isOptional: true }, + { name: 'timeout', type: 'number', isOptional: false }, + { name: 'priority', type: 'number', isOptional: false }, + { name: 'is_deleted', type: 'boolean', isOptional: false }, + ], + }), + ], +}); diff --git a/yarn.lock b/yarn.lock index 6d8598d..476d35e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19,6 +19,15 @@ js-tokens "^4.0.0" picocolors "^1.0.0" +"@babel/code-frame@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be" + integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg== + dependencies: + "@babel/helper-validator-identifier" "^7.27.1" + js-tokens "^4.0.0" + picocolors "^1.1.1" + "@babel/compat-data@^7.20.5", "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.26.8": version "7.26.8" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.8.tgz#821c1d35641c355284d4a870b8a4a7b0c141e367" @@ -56,6 +65,17 @@ "@jridgewell/trace-mapping" "^0.3.25" jsesc "^3.0.2" +"@babel/generator@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.27.1.tgz#862d4fad858f7208edd487c28b58144036b76230" + integrity sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w== + dependencies: + "@babel/parser" "^7.27.1" + "@babel/types" "^7.27.1" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + jsesc "^3.0.2" + "@babel/helper-annotate-as-pure@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz#d8eac4d2dc0d7b6e11fa6e535332e0d3184f06b4" @@ -63,6 +83,13 @@ dependencies: "@babel/types" "^7.25.9" +"@babel/helper-annotate-as-pure@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.1.tgz#4345d81a9a46a6486e24d069469f13e60445c05d" + integrity sha512-WnuuDILl9oOBbKnb4L+DyODx7iC47XfzmNCpTttFsSp6hTG7XZxu60+4IO+2/hPfcGOoKbFiwoI/+zwARbNQow== + dependencies: + "@babel/types" "^7.27.1" + "@babel/helper-compilation-targets@^7.20.7", "@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.25.9", "@babel/helper-compilation-targets@^7.26.5": version "7.27.0" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz#de0c753b1cd1d9ab55d473c5a5cf7170f0a81880" @@ -87,6 +114,19 @@ "@babel/traverse" "^7.27.0" semver "^6.3.1" +"@babel/helper-create-class-features-plugin@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.1.tgz#5bee4262a6ea5ddc852d0806199eb17ca3de9281" + integrity sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A== + dependencies: + "@babel/helper-annotate-as-pure" "^7.27.1" + "@babel/helper-member-expression-to-functions" "^7.27.1" + "@babel/helper-optimise-call-expression" "^7.27.1" + "@babel/helper-replace-supers" "^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" + "@babel/traverse" "^7.27.1" + semver "^6.3.1" + "@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.25.9": version "7.27.0" resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.27.0.tgz#0e41f7d38c2ebe06ebd9cf0e02fb26019c77cd95" @@ -115,6 +155,14 @@ "@babel/traverse" "^7.25.9" "@babel/types" "^7.25.9" +"@babel/helper-member-expression-to-functions@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz#ea1211276be93e798ce19037da6f06fbb994fa44" + integrity sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA== + dependencies: + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" + "@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz#e7f8d20602ebdbf9ebbea0a0751fb0f2a4141715" @@ -139,11 +187,23 @@ dependencies: "@babel/types" "^7.25.9" +"@babel/helper-optimise-call-expression@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz#c65221b61a643f3e62705e5dd2b5f115e35f9200" + integrity sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw== + dependencies: + "@babel/types" "^7.27.1" + "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.25.9", "@babel/helper-plugin-utils@^7.26.5", "@babel/helper-plugin-utils@^7.8.0": version "7.26.5" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz#18580d00c9934117ad719392c4f6585c9333cc35" integrity sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg== +"@babel/helper-plugin-utils@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz#ddb2f876534ff8013e6c2b299bf4d39b3c51d44c" + integrity sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw== + "@babel/helper-remap-async-to-generator@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz#e53956ab3d5b9fb88be04b3e2f31b523afd34b92" @@ -162,6 +222,15 @@ "@babel/helper-optimise-call-expression" "^7.25.9" "@babel/traverse" "^7.26.5" +"@babel/helper-replace-supers@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz#b1ed2d634ce3bdb730e4b52de30f8cccfd692bc0" + integrity sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.27.1" + "@babel/helper-optimise-call-expression" "^7.27.1" + "@babel/traverse" "^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers@^7.20.0", "@babel/helper-skip-transparent-expression-wrappers@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz#0b2e1b62d560d6b1954893fd2b705dc17c91f0c9" @@ -170,16 +239,34 @@ "@babel/traverse" "^7.25.9" "@babel/types" "^7.25.9" +"@babel/helper-skip-transparent-expression-wrappers@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz#62bb91b3abba8c7f1fec0252d9dbea11b3ee7a56" + integrity sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg== + dependencies: + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" + "@babel/helper-string-parser@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c" integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA== +"@babel/helper-string-parser@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687" + integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== + "@babel/helper-validator-identifier@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7" integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== +"@babel/helper-validator-identifier@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz#a7054dcc145a967dd4dc8fee845a57c1316c9df8" + integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow== + "@babel/helper-validator-option@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz#86e45bd8a49ab7e03f276577f96179653d41da72" @@ -209,6 +296,13 @@ dependencies: "@babel/types" "^7.27.0" +"@babel/parser@^7.27.1", "@babel/parser@^7.27.2": + version "7.27.2" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.27.2.tgz#577518bedb17a2ce4212afd052e01f7df0941127" + integrity sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw== + dependencies: + "@babel/types" "^7.27.1" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz#cc2e53ebf0a0340777fff5ed521943e253b4d8fe" @@ -263,6 +357,15 @@ "@babel/helper-create-class-features-plugin" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6" +"@babel/plugin-proposal-decorators@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.27.1.tgz#3686f424b2f8b2fee7579aa4df133a4f5244a596" + integrity sha512-DTxe4LBPrtFdsWzgpmbBKevg3e9PBy+dXRt19kSbucbZvL2uqtdqwwpluL1jfxYE0wIDTFp1nTy/q6gNLsxXrg== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/plugin-syntax-decorators" "^7.27.1" + "@babel/plugin-proposal-export-default-from@^7.0.0": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.25.9.tgz#52702be6ef8367fc8f18b8438278332beeb8f87c" @@ -318,6 +421,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.12.13" +"@babel/plugin-syntax-decorators@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.27.1.tgz#ee7dd9590aeebc05f9d4c8c0560007b05979a63d" + integrity sha512-YMq8Z87Lhl8EGkmb0MwYkt36QnxC+fzCgrl66ereamPlYToRpIk5nUjKUY3QKLWq8mwUB1BgbeXcTJhZOCDg5A== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/plugin-syntax-dynamic-import@^7.0.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" @@ -995,6 +1105,13 @@ pirates "^4.0.6" source-map-support "^0.5.16" +"@babel/runtime@7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.0.tgz#8600c2f595f277c60815256418b85356a65173c1" + integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw== + dependencies: + regenerator-runtime "^0.14.0" + "@babel/runtime@^7.0.0", "@babel/runtime@^7.8.4": version "7.27.0" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.27.0.tgz#fbee7cf97c709518ecc1f590984481d5460d4762" @@ -1011,6 +1128,15 @@ "@babel/parser" "^7.27.0" "@babel/types" "^7.27.0" +"@babel/template@^7.27.1": + version "7.27.2" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.2.tgz#fa78ceed3c4e7b63ebf6cb39e5852fca45f6809d" + integrity sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw== + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/parser" "^7.27.2" + "@babel/types" "^7.27.1" + "@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.25.9", "@babel/traverse@^7.26.10", "@babel/traverse@^7.26.5", "@babel/traverse@^7.26.8", "@babel/traverse@^7.27.0", "@babel/traverse@^7.4.3": version "7.27.0" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.27.0.tgz#11d7e644779e166c0442f9a07274d02cd91d4a70" @@ -1024,6 +1150,19 @@ debug "^4.3.1" globals "^11.1.0" +"@babel/traverse@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.27.1.tgz#4db772902b133bbddd1c4f7a7ee47761c1b9f291" + integrity sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg== + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/generator" "^7.27.1" + "@babel/parser" "^7.27.1" + "@babel/template" "^7.27.1" + "@babel/types" "^7.27.1" + debug "^4.3.1" + globals "^11.1.0" + "@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.25.9", "@babel/types@^7.26.10", "@babel/types@^7.27.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4": version "7.27.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.27.0.tgz#ef9acb6b06c3173f6632d993ecb6d4ae470b4559" @@ -1032,6 +1171,14 @@ "@babel/helper-string-parser" "^7.25.9" "@babel/helper-validator-identifier" "^7.25.9" +"@babel/types@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.27.1.tgz#9defc53c16fc899e46941fc6901a9eea1c9d8560" + integrity sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q== + dependencies: + "@babel/helper-string-parser" "^7.27.1" + "@babel/helper-validator-identifier" "^7.27.1" + "@cnakazawa/watch@^1.0.3": version "1.0.4" resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a" @@ -1324,6 +1471,29 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@nozbe/simdjson@3.9.4": + version "3.9.4" + resolved "https://registry.yarnpkg.com/@nozbe/simdjson/-/simdjson-3.9.4.tgz#64bb522c54cd22e40ff4a64d8f8e8e9285b123b6" + integrity sha512-/3oCP8GBpdyeiBMEnuI6S0yl0yekD6Qxfed67hZqU1GIVn3o/vZgE8qANm69THfw7JgHLS9zjx56F/dO3q+koA== + +"@nozbe/sqlite@3.46.0": + version "3.46.0" + resolved "https://registry.yarnpkg.com/@nozbe/sqlite/-/sqlite-3.46.0.tgz#aeda9df305e2f49ef951409e44544c19a5a3e32d" + integrity sha512-ntt8eNp5hh+axX9+kFb5uwyVE0edyfhiYYr+zHDzzFleGC7Qm+a2wHDWDtmRr5nSfbgomhY1uh30kpsHEIR3Mw== + +"@nozbe/watermelondb@^0.28.0": + version "0.28.0" + resolved "https://registry.yarnpkg.com/@nozbe/watermelondb/-/watermelondb-0.28.0.tgz#6130ac9017f9019966f892919ada79234c306c70" + integrity sha512-40ttcqPOLCTGnbfCQAXSEo8J4KlH/QQhwTfTb9E21CyX/driMEZueiJSI2rSkHICZrI2vnu52aRubNbI3UAzQQ== + dependencies: + "@babel/runtime" "7.26.0" + "@nozbe/simdjson" "3.9.4" + "@nozbe/sqlite" "3.46.0" + hoist-non-react-statics "^3.3.2" + lokijs "npm:@nozbe/lokijs@1.5.12-wmelon6" + rxjs "^7.8.1" + sql-escape-string "^1.1.0" + "@react-native-community/bob@^0.17.1": version "0.17.1" resolved "https://registry.yarnpkg.com/@react-native-community/bob/-/bob-0.17.1.tgz#72d71747208e6cf534f14ee7e5a0d39562f6d768" @@ -4056,6 +4226,13 @@ highlight.js@^9.17.1: resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.18.5.tgz#d18a359867f378c138d6819edfc2a8acd5f29825" integrity sha512-a5bFyofd/BHCX52/8i8uJkjr9DYwXIPnM/plwI6W7ezItLGqzt7X2G2nXuYSfsIJdkwwj/g9DG1LkcGJI/dDoA== +hoist-non-react-statics@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + dependencies: + react-is "^16.7.0" + hosted-git-info@^2.1.4: version "2.8.9" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" @@ -5379,6 +5556,11 @@ logkitty@^0.6.0: dayjs "^1.8.15" yargs "^12.0.5" +"lokijs@npm:@nozbe/lokijs@1.5.12-wmelon6": + version "1.5.12-wmelon6" + resolved "https://registry.yarnpkg.com/@nozbe/lokijs/-/lokijs-1.5.12-wmelon6.tgz#e457d934d614d5df80105c86314252a6e614df9b" + integrity sha512-GXsaqY8qTJ6xdCrGyno2t+ON2aj6PrUDdvhbrkxK/0Fp12C4FGvDg1wS+voLU9BANYHEnr7KRWfItDZnQkjoAg== + loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" @@ -6632,7 +6814,7 @@ react-devtools-core@^3.6.1: shell-quote "^1.6.1" ws "^3.3.1" -react-is@^16.13.1, react-is@^16.8.4: +react-is@^16.13.1, react-is@^16.7.0, react-is@^16.8.4: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== @@ -7038,6 +7220,13 @@ rxjs@^5.4.3: dependencies: symbol-observable "1.0.1" +rxjs@^7.8.1: + version "7.8.2" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.2.tgz#955bc473ed8af11a002a2be52071bf475638607b" + integrity sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA== + dependencies: + tslib "^2.1.0" + safe-array-concat@^1.1.2, safe-array-concat@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.3.tgz#c9e54ec4f603b0bbb8e7e5007a5ee7aecd1538c3" @@ -7474,6 +7663,11 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== +sql-escape-string@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/sql-escape-string/-/sql-escape-string-1.1.0.tgz#fe744b8514868c0eb4bfb9e4a989271d40f30eb9" + integrity sha512-/kqO4pLZSLfV0KsBM2xkVh2S3GbjJJone37d7gYwLyP0c+REh3vnmkhQ7VwNrX76igC0OhJWpTg0ukkdef9vvA== + sshpk@^1.7.0: version "1.18.0" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.18.0.tgz#1663e55cddf4d688b86a46b77f0d5fe363aba028" @@ -7822,6 +8016,11 @@ tslib@^1.8.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== +tslib@^2.1.0: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"