This commit is contained in:
Manav Rathi
2024-08-14 09:11:56 +05:30
parent 82b8658268
commit d5d0e98197

View File

@@ -1,5 +1,6 @@
import { decryptAssociatedB64Data } from "@/base/crypto/ente";
import { authenticatedRequestHeaders, ensureOk } from "@/base/http";
import { getKVN, setKV } from "@/base/kv";
import { apiURL } from "@/base/origins";
import { z } from "zod";
@@ -51,6 +52,10 @@ const defaultDiffLimit = 500;
* expected to be associated with this entity type.
*/
interface UserEntity {
/**
* A UUID or nanoid for the entity.
*/
id: string;
/**
* Arbitrary data associated with the entity. The format of this data is
* specific to each entity type.
@@ -65,6 +70,7 @@ interface UserEntity {
}
const RemoteUserEntity = z.object({
id: z.string(),
/** Base64 string containing the encrypted contents of the entity. */
encryptedData: z.string(),
/** Base64 string containing the decryption header. */
@@ -74,8 +80,8 @@ const RemoteUserEntity = z.object({
});
/**
* Fetch all user entities of the given type that have been created or updated
* since the given time.
* Fetch the next batch of user entities of the given type that have been
* created or updated since the given time.
*
* @param type The type of the entities to fetch.
*
@@ -113,7 +119,8 @@ export const userEntityDiff = async (
.parse(await res.json()).diff;
return Promise.all(
entities.map(
async ({ encryptedData, header, isDeleted, updatedAt }) => ({
async ({ id, encryptedData, header, isDeleted, updatedAt }) => ({
id,
data: isDeleted
? undefined
: await decrypt(encryptedData, header),
@@ -123,6 +130,43 @@ export const userEntityDiff = async (
);
};
/**
* Sync the {@link Person} entities that we have locally with remote.
*
* This fetches all the user entities corresponding to the "person_v2" entity
* type from remote that have been created, updated or deleted since the last
* time we checked. This diff is then applied to the data we have persisted
* locally.
*/
export const personDiff = async (
entityKeyB64: string,
): Promise<RemotePerson[]> => {
const sinceTime = 0;
const parse = (data: Uint8Array) =>
RemotePerson.parse(JSON.parse(new TextDecoder().decode(data)));
const result: RemotePerson[] = [];
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition, no-constant-condition
while (true) {
const entities = await userEntityDiff("person", 0, entityKeyB64);
if (entities.length == 0) break;
const latestUpdatedAt = entities.reduce(
(max, e) => Math.max(max, e.updatedAt),
sinceTime,
);
const people = entities
.map(({ data }) => (data ? parse(data) : undefined))
.filter((p) => !!p);
// TODO-Cluster
console.log({ latestUpdatedAt, people });
return people;
}
return result;
};
/**
* Zod schema for the "person" entity (the {@link RemotePerson} type).
*/
@@ -140,27 +184,21 @@ const RemotePerson = z.object({
/**
* A "person" entity as synced via remote.
*/
export type RemotePerson = z.infer<typeof RemotePerson>;
type RemotePerson = z.infer<typeof RemotePerson>;
const latestUpdatedAtKey = (type: EntityType) => `latestUpdatedAt/${type}`;
/**
* Fetch all Person entities that have been created or updated since the last
* time we checked.
* Return the locally persisted value for the latest `updatedAt` time for the
* given entity type.
*
* This is used to checkpoint diffs, so that we can resume fetching from the
* last time we did a fetch.
*/
export const personDiff = async (
entityKeyB64: string,
): Promise<RemotePerson[]> => {
const sinceTime = 0;
const entities = await userEntityDiff("person", 0, entityKeyB64);
const latestUpdatedAt = entities.reduce(
(max, e) => Math.max(max, e.updatedAt),
sinceTime,
);
const parse = (data: Uint8Array) =>
RemotePerson.parse(JSON.parse(new TextDecoder().decode(data)));
const people = entities
.map(({ data }) => (data ? parse(data) : undefined))
.filter((p) => !!p);
// TODO-Cluster
console.log({ latestUpdatedAt, people });
return people;
};
const latestUpdatedAt = (type: EntityType) => getKVN(latestUpdatedAtKey(type));
/**
* Setter for {@link latestUpdatedAt}.
*/
const setLatestUpdatedAt = (type: EntityType, value: number) =>
setKV(latestUpdatedAtKey(type), value);