Page MenuHomePhabricator

D11581.diff
No OneTemporary

D11581.diff

diff --git a/lib/ops/thread-activity-store-ops.js b/lib/ops/thread-activity-store-ops.js
--- a/lib/ops/thread-activity-store-ops.js
+++ b/lib/ops/thread-activity-store-ops.js
@@ -130,4 +130,7 @@
},
};
-export { threadActivityStoreOpsHandlers };
+export {
+ threadActivityStoreOpsHandlers,
+ convertThreadActivityEntryToClientDBThreadActivityEntry,
+};
diff --git a/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h b/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h
--- a/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h
+++ b/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h
@@ -15,6 +15,7 @@
#include "entities/Report.h"
#include "entities/SyncedMetadataEntry.h"
#include "entities/Thread.h"
+#include "entities/ThreadActivityEntry.h"
#include "entities/UserInfo.h"
#include <string>
@@ -99,6 +100,13 @@
removeAuxUserInfos(const std::vector<std::string> &ids) const = 0;
virtual void removeAllAuxUserInfos() const = 0;
virtual std::vector<AuxUserInfo> getAllAuxUserInfos() const = 0;
+ virtual void replaceThreadActivityEntry(
+ const ThreadActivityEntry &thread_activity_entry) const = 0;
+ virtual void
+ removeThreadActivityEntries(const std::vector<std::string> &ids) const = 0;
+ virtual void removeAllThreadActivityEntries() const = 0;
+ virtual std::vector<ThreadActivityEntry>
+ getAllThreadActivityEntries() const = 0;
virtual void beginTransaction() const = 0;
virtual void commitTransaction() const = 0;
virtual void rollbackTransaction() const = 0;
diff --git a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h
--- a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h
+++ b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h
@@ -8,6 +8,7 @@
#include "entities/Draft.h"
#include "entities/IntegrityThreadHash.h"
#include "entities/KeyserverInfo.h"
+#include "entities/ThreadActivityEntry.h"
#include "entities/UserInfo.h"
#include <mutex>
@@ -113,6 +114,12 @@
void removeAuxUserInfos(const std::vector<std::string> &ids) const override;
void removeAllAuxUserInfos() const override;
virtual std::vector<AuxUserInfo> getAllAuxUserInfos() const override;
+ void replaceThreadActivityEntry(
+ const ThreadActivityEntry &thread_activity_entry) const override;
+ void removeThreadActivityEntries(
+ const std::vector<std::string> &ids) const override;
+ void removeAllThreadActivityEntries() const override;
+ std::vector<ThreadActivityEntry> getAllThreadActivityEntries() const override;
void beginTransaction() const override;
void commitTransaction() const override;
void rollbackTransaction() const override;
diff --git a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp
--- a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp
+++ b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp
@@ -1863,6 +1863,51 @@
SQLiteQueryExecutor::getConnection(), getAllAuxUserInfosSQL);
}
+void SQLiteQueryExecutor::replaceThreadActivityEntry(
+ const ThreadActivityEntry &thread_activity_entry) const {
+ static std::string replaceThreadActivityEntrySQL =
+ "REPLACE INTO thread_activity (id, thread_activity_store_entry) "
+ "VALUES (?, ?);";
+ replaceEntity<ThreadActivityEntry>(
+ SQLiteQueryExecutor::getConnection(),
+ replaceThreadActivityEntrySQL,
+ thread_activity_entry);
+}
+
+void SQLiteQueryExecutor::removeAllThreadActivityEntries() const {
+ static std::string removeAllThreadActivityEntriesSQL =
+ "DELETE FROM thread_activity;";
+ removeAllEntities(
+ SQLiteQueryExecutor::getConnection(), removeAllThreadActivityEntriesSQL);
+}
+
+void SQLiteQueryExecutor::removeThreadActivityEntries(
+ const std::vector<std::string> &ids) const {
+ if (!ids.size()) {
+ return;
+ }
+
+ std::stringstream removeThreadActivityEntriesByKeysSQLStream;
+ removeThreadActivityEntriesByKeysSQLStream << "DELETE FROM thread_activity "
+ "WHERE id IN "
+ << getSQLStatementArray(ids.size())
+ << ";";
+
+ removeEntitiesByKeys(
+ SQLiteQueryExecutor::getConnection(),
+ removeThreadActivityEntriesByKeysSQLStream.str(),
+ ids);
+}
+
+std::vector<ThreadActivityEntry>
+SQLiteQueryExecutor::getAllThreadActivityEntries() const {
+ static std::string getAllThreadActivityEntriesSQL =
+ "SELECT * "
+ "FROM thread_activity;";
+ return getAllEntities<ThreadActivityEntry>(
+ SQLiteQueryExecutor::getConnection(), getAllThreadActivityEntriesSQL);
+}
+
void SQLiteQueryExecutor::beginTransaction() const {
executeQuery(SQLiteQueryExecutor::getConnection(), "BEGIN TRANSACTION;");
}
diff --git a/native/cpp/CommonCpp/DatabaseManagers/entities/ThreadActivityEntry.h b/native/cpp/CommonCpp/DatabaseManagers/entities/ThreadActivityEntry.h
new file mode 100644
--- /dev/null
+++ b/native/cpp/CommonCpp/DatabaseManagers/entities/ThreadActivityEntry.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "SQLiteDataConverters.h"
+#include <sqlite3.h>
+#include <string>
+
+namespace comm {
+
+struct ThreadActivityEntry {
+ std::string id;
+ std::string thread_activity_store_entry;
+
+ static ThreadActivityEntry fromSQLResult(sqlite3_stmt *sqlRow, int idx) {
+ return ThreadActivityEntry{
+ getStringFromSQLRow(sqlRow, idx), getStringFromSQLRow(sqlRow, idx + 1)};
+ }
+
+ int bindToSQL(sqlite3_stmt *sql, int idx) const {
+ bindStringToSQL(id, sql, idx);
+ return bindStringToSQL(thread_activity_store_entry, sql, idx + 1);
+ }
+};
+
+} // namespace comm
diff --git a/web/cpp/SQLiteQueryExecutorBindings.cpp b/web/cpp/SQLiteQueryExecutorBindings.cpp
--- a/web/cpp/SQLiteQueryExecutorBindings.cpp
+++ b/web/cpp/SQLiteQueryExecutorBindings.cpp
@@ -62,6 +62,9 @@
value_object<AuxUserInfo>("AuxUserInfo")
.field("id", &AuxUserInfo::id)
.field("auxUserInfo", &AuxUserInfo::aux_user_info);
+ value_object<ThreadActivityEntry>("ThreadActivityEntry")
+ .field("id", &ThreadActivityEntry::id)
+ .field("threadActivityStoreEntry", &ThreadActivityEntry::thread_activity_store_entry);
value_object<WebThread>("WebThread")
.field("id", &WebThread::id)
@@ -213,6 +216,18 @@
.function(
"removeAllAuxUserInfos", &SQLiteQueryExecutor::removeAllAuxUserInfos)
.function("getAllAuxUserInfos", &SQLiteQueryExecutor::getAllAuxUserInfos)
+ .function(
+ "replaceThreadActivityEntry",
+ &SQLiteQueryExecutor::replaceThreadActivityEntry)
+ .function(
+ "removeThreadActivityEntries",
+ &SQLiteQueryExecutor::removeThreadActivityEntries)
+ .function(
+ "removeAllThreadActivityEntries",
+ &SQLiteQueryExecutor::removeAllThreadActivityEntries)
+ .function(
+ "getAllThreadActivityEntries",
+ &SQLiteQueryExecutor::getAllThreadActivityEntries)
.function("beginTransaction", &SQLiteQueryExecutor::beginTransaction)
.function("commitTransaction", &SQLiteQueryExecutor::commitTransaction)
.function(
diff --git a/web/shared-worker/_generated/comm_query_executor.wasm b/web/shared-worker/_generated/comm_query_executor.wasm
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
literal 0
Hc$@<O00001
diff --git a/web/shared-worker/queries/thread-activity-queries.test.js b/web/shared-worker/queries/thread-activity-queries.test.js
new file mode 100644
--- /dev/null
+++ b/web/shared-worker/queries/thread-activity-queries.test.js
@@ -0,0 +1,117 @@
+// @flow
+
+import { threadActivityStoreOpsHandlers } from 'lib/ops/thread-activity-store-ops.js';
+
+import { getDatabaseModule } from '../db-module.js';
+import type { EmscriptenModule } from '../types/module.js';
+import { type SQLiteQueryExecutor } from '../types/sqlite-query-executor.js';
+import { clearSensitiveData } from '../utils/db-utils.js';
+
+const FILE_PATH = 'test.sqlite';
+
+describe('ThreadActivity Store queries', () => {
+ let queryExecutor: ?SQLiteQueryExecutor = null;
+ let dbModule: ?EmscriptenModule = null;
+
+ beforeAll(async () => {
+ dbModule = getDatabaseModule();
+ });
+
+ beforeEach(() => {
+ if (!dbModule) {
+ throw new Error('Database module is missing');
+ }
+ queryExecutor = new dbModule.SQLiteQueryExecutor(FILE_PATH);
+ if (!queryExecutor) {
+ throw new Error('SQLiteQueryExecutor is missing');
+ }
+ queryExecutor?.replaceThreadActivityEntry({
+ id: 'test_id_1',
+ threadActivityStoreEntry: JSON.stringify({
+ lastNavigatedTo: 1,
+ lastPruned: 2,
+ }),
+ });
+ queryExecutor?.replaceThreadActivityEntry({
+ id: 'test_id_2',
+ threadActivityStoreEntry: JSON.stringify({
+ lastNavigatedTo: 3,
+ lastPruned: 4,
+ }),
+ });
+ queryExecutor?.replaceThreadActivityEntry({
+ id: 'test_id_3',
+ threadActivityStoreEntry: JSON.stringify({
+ lastNavigatedTo: 5,
+ lastPruned: 6,
+ }),
+ });
+ });
+
+ afterEach(() => {
+ if (!dbModule || !queryExecutor) {
+ return;
+ }
+
+ clearSensitiveData(dbModule, FILE_PATH, queryExecutor);
+ });
+
+ it('should return all thread activity entries', () => {
+ const threadActivityEntries = queryExecutor?.getAllThreadActivityEntries();
+
+ expect(threadActivityEntries).toHaveLength(3);
+ });
+
+ it('should remove all thread activity entries', () => {
+ queryExecutor?.removeAllThreadActivityEntries();
+ const threadActivityEntries = queryExecutor?.getAllThreadActivityEntries();
+
+ expect(threadActivityEntries).toHaveLength(0);
+ });
+
+ it('should update thread activity entry test_id_2', () => {
+ queryExecutor?.replaceThreadActivityEntry({
+ id: 'test_id_2',
+ threadActivityStoreEntry: JSON.stringify({
+ lastNavigatedTo: 7,
+ lastPruned: 8,
+ }),
+ });
+
+ const threadActivityEntries = queryExecutor?.getAllThreadActivityEntries();
+ if (!threadActivityEntries) {
+ throw new Error('thread activity entries not defined');
+ }
+
+ expect(threadActivityEntries).toHaveLength(3);
+
+ const threadActivityEntriesFromDB =
+ threadActivityStoreOpsHandlers.translateClientDBData(
+ threadActivityEntries,
+ );
+
+ expect(threadActivityEntriesFromDB['test_id_2']).toBeDefined();
+ expect(threadActivityEntriesFromDB['test_id_2']).toStrictEqual({
+ lastNavigatedTo: 7,
+ lastPruned: 8,
+ });
+ });
+
+ it('should remove thread activity entries test_id_1 and test_id_3', () => {
+ queryExecutor?.removeThreadActivityEntries(['test_id_1', 'test_id_3']);
+
+ const threadActivityEntries = queryExecutor?.getAllThreadActivityEntries();
+ if (!threadActivityEntries) {
+ throw new Error('thread activity entries not defined');
+ }
+
+ expect(threadActivityEntries.length).toBe(1);
+
+ const threadActivityEntriesFromDB =
+ threadActivityStoreOpsHandlers.translateClientDBData(
+ threadActivityEntries,
+ );
+
+ expect(threadActivityEntriesFromDB['test_id_2']).toBeDefined();
+ });
+});
diff --git a/web/shared-worker/types/sqlite-query-executor.js b/web/shared-worker/types/sqlite-query-executor.js
--- a/web/shared-worker/types/sqlite-query-executor.js
+++ b/web/shared-worker/types/sqlite-query-executor.js
@@ -6,6 +6,7 @@
import type { ClientDBKeyserverInfo } from 'lib/ops/keyserver-store-ops.js';
import type { ClientDBReport } from 'lib/ops/report-store-ops.js';
import type { ClientDBSyncedMetadataEntry } from 'lib/ops/synced-metadata-store-ops.js';
+import type { ClientDBThreadActivityEntry } from 'lib/ops/thread-activity-store-ops.js';
import type { ClientDBUserInfo } from 'lib/ops/user-store-ops.js';
import type { ClientDBDraftInfo } from 'lib/types/draft-types.js';
@@ -136,6 +137,13 @@
removeAllAuxUserInfos(): void;
getAllAuxUserInfos(): ClientDBAuxUserInfo[];
+ replaceThreadActivityEntry(
+ threadActivityEntry: ClientDBThreadActivityEntry,
+ ): void;
+ removeThreadActivityEntries(ids: $ReadOnlyArray<string>): void;
+ removeAllThreadActivityEntries(): void;
+ getAllThreadActivityEntries(): ClientDBThreadActivityEntry[];
+
beginTransaction(): void;
commitTransaction(): void;
rollbackTransaction(): void;

File Metadata

Mime Type
text/plain
Expires
Tue, Dec 3, 9:04 PM (9 m, 58 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2610390
Default Alt Text
D11581.diff (12 KB)

Event Timeline