Skip to content

Commit

Permalink
records can be updated without being stored
Browse files Browse the repository at this point in the history
  • Loading branch information
LiranCohen committed Oct 21, 2024
1 parent 5120f6f commit de78427
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 74 deletions.
6 changes: 5 additions & 1 deletion packages/api/src/record.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ export type RecordUpdateParams = {
*/
dataCid?: DwnMessageDescriptor[DwnInterface.RecordsWrite]['dataCid'];

/** Whether or not to store the updated message. */
store?: boolean;

/** The data format/MIME type of the supplied data */
dataFormat?: string;

Expand Down Expand Up @@ -706,7 +709,7 @@ export class Record implements RecordModel {
*
* @beta
*/
async update({ dateModified, data, protocolRole, ...params }: RecordUpdateParams): Promise<DwnResponseStatus> {
async update({ dateModified, data, protocolRole, store = true, ...params }: RecordUpdateParams): Promise<DwnResponseStatus> {

if (this.deleted) {
throw new Error('Record: Cannot revive a deleted record.');
Expand Down Expand Up @@ -760,6 +763,7 @@ export class Record implements RecordModel {
messageParams : { ...updateMessage },
messageType : DwnInterface.RecordsWrite,
target : this._connectedDid,
store
};

if (this._delegateDid) {
Expand Down
152 changes: 79 additions & 73 deletions packages/api/tests/record.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ if (!globalThis.crypto) globalThis.crypto = webcrypto;

let testDwnUrls: string[] = [testDwnUrl];

describe('Record', () => {
describe.only('Record', () => {
let dataText: string;
let dataBlob: Blob;
let dataFormat: string;
Expand Down Expand Up @@ -2611,58 +2611,6 @@ describe('Record', () => {
expect(readResultAfterUpdate.status.code).to.equal(401);
});

it('updates a record locally that only written to a remote DWN', async () => {
// Create a record but do not store it on the local DWN.
const { status, record } = await dwnAlice.records.write({
store : false,
data : 'Hello, world!',
message : {
schema : 'foo/bar',
dataFormat : 'text/plain'
}
});
expect(status.code).to.equal(202);
expect(record).to.not.be.undefined;

// Store the data CID of the record before it is updated.
const dataCidBeforeDataUpdate = record!.dataCid;

// Write the record to a remote DWN.
const { status: sendStatus } = await record!.send(aliceDid.uri);
expect(sendStatus.code).to.equal(202);

// fails because record has not been stored in the local dwn yet
let updateResult = await record!.update({ data: 'bye' });
expect(updateResult.status.code).to.equal(400);
expect(updateResult.status.detail).to.equal('RecordsWriteGetInitialWriteNotFound: Initial write is not found.');

const { status: recordStoreStatus }= await record.store();
expect(recordStoreStatus.code).to.equal(202);

// now succeeds with the update
updateResult = await record!.update({ data: 'bye' });
expect(updateResult.status.code).to.equal(202);

// Confirm that the record was written to the local DWN.
const readResult = await dwnAlice.records.read({
message: {
filter: {
recordId: record!.id
}
}
});
expect(readResult.status.code).to.equal(200);
expect(readResult.record).to.not.be.undefined;

// Confirm that the data CID of the record was updated.
expect(readResult.record.dataCid).to.not.equal(dataCidBeforeDataUpdate);
expect(readResult.record.dataCid).to.equal(record!.dataCid);

// Confirm that the data payload of the record was modified.
const updatedData = await record!.data.text();
expect(updatedData).to.equal('bye');
});

it('allows to update a record locally that was initially read from a remote DWN if store() is issued', async () => {
// Create a record but do not store it on the local DWN.
const { status, record } = await dwnAlice.records.write({
Expand Down Expand Up @@ -2725,7 +2673,7 @@ describe('Record', () => {
expect(readResult.record.dataCid).to.equal(readRecord.dataCid);
});

it('updates a record locally that was initially queried from a remote DWN', async () => {
it('updates a record that was queried from a remote DWN without storing it', async () => {
// Create a record but do not store it on the local DWN.
const { status, record } = await dwnAlice.records.write({
store : false,
Expand All @@ -2746,7 +2694,7 @@ describe('Record', () => {
expect(sendStatus.code).to.equal(202);

// Query the record from the remote DWN.
const queryResult = await dwnAlice.records.query({
let queryResult = await dwnAlice.records.query({
from : aliceDid.uri,
message : {
filter: {
Expand All @@ -2758,37 +2706,95 @@ describe('Record', () => {
expect(queryResult.records).to.not.be.undefined;
expect(queryResult.records.length).to.equal(1);

// Attempt to update the queried record, which will fail because we haven't stored the queried record locally yet
// Attempt to update the queried record
const [ queriedRecord ] = queryResult.records;
let updateResult = await queriedRecord!.update({ data: 'bye' });
expect(updateResult.status.code).to.equal(400);
expect(updateResult.status.detail).to.equal('RecordsWriteGetInitialWriteNotFound: Initial write is not found.');

// store the queried record
const { status: queriedStoreStatus } = await queriedRecord.store();
expect(queriedStoreStatus.code).to.equal(202);

updateResult = await queriedRecord!.update({ data: 'bye' });
let updateResult = await queriedRecord!.update({ data: 'Updated, world!', store: false });
expect(updateResult.status.code).to.equal(202);

// Confirm that the record was written to the local DWN.
const readResult = await dwnAlice.records.read({
// confirm that the record does not exist locally
queryResult = await dwnAlice.records.read({
message: {
filter: {
recordId: record!.id
}
}
});
expect(queryResult.status.code).to.equal(404);
});

it('updates a record which has a parent reference from a remote DWN without storing it or its parent', async () => {
// create a parent thread
const { status: threadStatus, record: threadRecord } = await dwnAlice.records.write({
store : false,
data : 'Hello, world!',
message : {
protocol : protocolDefinition.protocol,
schema : protocolDefinition.types.thread.schema,
protocolPath : 'thread'
}
});

expect(threadStatus.code).to.equal(202);
expect(threadRecord).to.not.be.undefined;

const { status: threadSendStatus } = await threadRecord.send();
expect(threadSendStatus.code).to.equal(202);

// create an email with the thread as a parent
const { status: emailStatus, record: emailRecord } = await dwnAlice.records.write({
store : false,
data : 'Hello, world!',
message : {
parentContextId : threadRecord.contextId,
protocol : protocolDefinition.protocol,
protocolPath : 'thread/email',
schema : protocolDefinition.types.email.schema
}
});
expect(emailStatus.code).to.equal(202);
expect(emailRecord).to.not.be.undefined;

const { status: emailSendStatus } = await emailRecord!.send();
expect(emailSendStatus.code).to.equal(202);

// update email record
const { status: updateStatus } = await emailRecord!.update({ data: 'updated email record', store: false });
expect(updateStatus.code).to.equal(202);

const { status: updateEmailSendStatus } = await emailRecord!.send();
expect(updateEmailSendStatus.code).to.equal(202);

let readResult = await dwnAlice.records.read({
from: aliceDid.uri,
message: {
filter: {
recordId: emailRecord.id
}
}
});

expect(readResult.status.code).to.equal(200);
expect(readResult.record).to.not.be.undefined;
expect(await readResult.record.data.text()).to.equal('updated email record');

// Confirm that the data CID of the record was updated.
expect(readResult.record.dataCid).to.not.equal(dataCidBeforeDataUpdate);
expect(readResult.record.dataCid).to.equal(queriedRecord!.dataCid);
// confirm that records do not exist locally
readResult = await dwnAlice.records.read({
message: {
filter: {
recordId: emailRecord.id
}
}
});
expect(readResult.status.code).to.equal(404);

// Confirm that the data payload of the record was modified.
const updatedData = await queriedRecord!.data.text();
expect(updatedData).to.equal('bye');
readResult = await dwnAlice.records.read({
message: {
filter: {
recordId: threadRecord.id
}
}
});
expect(readResult.status.code).to.equal(404);
});

it('updates a record which has a parent reference', async () => {
Expand Down

0 comments on commit de78427

Please sign in to comment.