Skip to content

Commit 2e61589

Browse files
committed
sync with java: d3ec2c31bb8774b8cf3e07b3df4a759b277da483
1 parent 1568c5a commit 2e61589

File tree

6 files changed

+219
-8
lines changed

6 files changed

+219
-8
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { RollingIndexState } from "./RollingIndexState";
2+
3+
export interface RollingIndexDeployment {
4+
state: RollingIndexState;
5+
createdAt: Date;
6+
startedAt: Date;
7+
finishedAt: Date;
8+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { IOperation, OperationResultType } from "../OperationAbstractions";
2+
import { RevisionsResult } from "./RevisionsResult";
3+
import { DocumentType } from "../../DocumentAbstractions";
4+
import { IDocumentStore } from "../../IDocumentStore";
5+
import { DocumentConventions } from "../../Conventions/DocumentConventions";
6+
import { HttpCache } from "../../../Http/HttpCache";
7+
import { RavenCommand } from "../../../Http/RavenCommand";
8+
import { GetRevisionsCommand } from "../../Commands/GetRevisionsCommand";
9+
import { ServerNode } from "../../../Http/ServerNode";
10+
import { HttpRequestParameters } from "../../../Primitives/Http";
11+
import * as stream from "readable-stream";
12+
13+
export class GetRevisionsOperation<T extends object> implements IOperation<RevisionsResult<T>> {
14+
private readonly _parameters: GetRevisionsParameters<T>;
15+
private readonly _id: string;
16+
17+
public constructor(id: string, parameters: GetRevisionsParameters<T> = {}) {
18+
this._id = id;
19+
this._parameters = parameters;
20+
}
21+
22+
public get resultType(): OperationResultType {
23+
return "CommandResult";
24+
}
25+
26+
27+
getCommand(store: IDocumentStore, conventions: DocumentConventions, httpCache: HttpCache): RavenCommand<RevisionsResult<T>> {
28+
return new GetRevisionsResultCommand(this._id, this._parameters, conventions);
29+
}
30+
}
31+
class GetRevisionsResultCommand<T extends object> extends RavenCommand<RevisionsResult<T>> {
32+
private readonly _parameters: GetRevisionsParameters<T>;
33+
private readonly conventions: DocumentConventions;
34+
private readonly _id: string;
35+
private readonly _cmd: GetRevisionsCommand;
36+
37+
public constructor(id: string, parameters: GetRevisionsParameters<T>, conventions: DocumentConventions) {
38+
super();
39+
this.conventions = conventions;
40+
this._id = id;
41+
this._parameters = parameters;
42+
this._cmd = new GetRevisionsCommand(conventions, id, parameters.start, parameters.pageSize);
43+
}
44+
45+
get isReadRequest(): boolean {
46+
return true;
47+
}
48+
49+
createRequest(node: ServerNode): HttpRequestParameters {
50+
return this._cmd.createRequest(node);
51+
}
52+
53+
54+
async setResponseAsync(bodyStream: stream.Stream, fromCache: boolean): Promise<string> {
55+
if (!bodyStream) {
56+
return ;
57+
}
58+
59+
let body: string;
60+
61+
const responseNode = await this._pipeline<any>()
62+
.parseJsonSync()
63+
.collectBody(b => body = b)
64+
.process(bodyStream);
65+
66+
if (!responseNode.Results) {
67+
return body;
68+
}
69+
70+
const revisions = responseNode.Results;
71+
72+
const total = responseNode.TotalResults;
73+
74+
const result = new RevisionsResult<T>();
75+
result.totalResults = total;
76+
result.results = revisions.filter(x => x).map(x => {
77+
const entityType = this.conventions.getJsTypeByDocumentType(this._parameters.documentType);
78+
return this.conventions.deserializeEntityFromJson(entityType, x);
79+
});
80+
81+
this.result = result;
82+
}
83+
}
84+
85+
export interface GetRevisionsParameters<T extends object> {
86+
documentType?: DocumentType<T>;
87+
start?: number;
88+
pageSize?: number;
89+
}

src/Documents/Session/Operations/Lazy/LazyRevisionOperations.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,16 @@ export class LazyRevisionOperations implements ILazyRevisionsOperations {
5757
private _get<TEntity extends object>(changeVectorOrVectors: string | string[],
5858
documentType?: DocumentType<TEntity>)
5959
: Lazy<RevisionsCollectionObject<TEntity> | TEntity> {
60-
const operation = new GetRevisionOperation(this.delegate, changeVectorOrVectors as string);
61-
const lazyRevisionOperation = new LazyRevisionOperation(documentType, operation, "Map");
62-
return this.delegate.addLazyOperation(lazyRevisionOperation);
60+
if (TypeUtil.isArray(changeVectorOrVectors)) {
61+
const operation = new GetRevisionOperation(this.delegate, changeVectorOrVectors);
62+
const lazyRevisionOperation = new LazyRevisionOperation(documentType, operation, "Map");
63+
return this.delegate.addLazyOperation(lazyRevisionOperation);
64+
} else {
65+
const operation = new GetRevisionOperation(this.delegate, changeVectorOrVectors);
66+
const lazyRevisionOperation = new LazyRevisionOperation(documentType, operation, "Single");
67+
return this.delegate.addLazyOperation(lazyRevisionOperation);
68+
}
69+
6370
}
6471

6572
private _getByIdAndDate<TEntity extends object>(id: string, date: Date, clazz?: DocumentType<TEntity>): Lazy<TEntity> {

src/ServerWide/Operations/GetDatabaseRecordOperation.ts

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import { RavenCommand } from "../../Http/RavenCommand";
77
import { ServerNode } from "../../Http/ServerNode";
88
import { TimeSeriesConfiguration } from "../../Documents/Operations/TimeSeries/TimeSeriesConfiguration";
99
import { ServerResponse } from "../../Types";
10+
import { RollingIndexDeployment } from "../../Documents/Indexes/RollingIndexDeployment";
11+
import { DateUtil } from "../../Utility/DateUtil";
1012

1113
export class GetDatabaseRecordOperation implements IServerOperation<DatabaseRecordWithEtag> {
1214
private readonly _database: string;
@@ -58,25 +60,37 @@ export class GetDatabaseRecordCommand extends RavenCommand<DatabaseRecordWithEta
5860
.objectKeysTransform({
5961
defaultTransform: "camel",
6062
ignorePaths: [
61-
/^(indexes|sorters|autoIndexes|settings|indexesHistory|ravenConnectionStrings|sqlConnectionStrings)\.[^.]+$/i,
63+
/^(indexes|sorters|autoIndexes|settings|indexesHistory|ravenConnectionStrings|sqlConnectionStrings|rollingIndexes)\.[^.]+$/i,
64+
/^rollingIndexes\.[^.]+\.activeDeployments\.[^.]+$/i,
65+
/^indexesHistory\.[^.]+\.[^.]+\.rollingDeployment\.[^.]+$/i,
6266
/^timeSeries\./i
6367
]
6468
})
6569
.process(bodyStream);
6670

71+
const dateUtil = this._conventions.dateUtil;
72+
73+
if (this.result.rollingIndexes) {
74+
Object.values(this.result.rollingIndexes).forEach(index => {
75+
if (index.activeDeployments) {
76+
index.activeDeployments = GetDatabaseRecordCommand.mapRollingDeployment(dateUtil, index.activeDeployments as any);
77+
}
78+
});
79+
}
6780

6881
const history = this.result.indexesHistory;
6982
if (history) {
70-
const dateUtil = this._conventions.dateUtil;
83+
7184
for (const indexName of Object.keys(history)) {
7285
const indexHistory = history[indexName];
7386

7487
history[indexName] = indexHistory.map(item => {
75-
const { createdAt, ...otherHistoryProps } = item as unknown as ServerResponse<IndexHistoryEntry>;
88+
const { createdAt, rollingDeployment, ...otherHistoryProps } = item as unknown as ServerResponse<IndexHistoryEntry>;
7689

7790
return {
7891
...otherHistoryProps,
79-
createdAt: dateUtil.parse(createdAt)
92+
createdAt: dateUtil.parse(createdAt),
93+
rollingDeployment: GetDatabaseRecordCommand.mapRollingDeployment(dateUtil, rollingDeployment)
8094
} as IndexHistoryEntry;
8195
});
8296
}
@@ -88,4 +102,23 @@ export class GetDatabaseRecordCommand extends RavenCommand<DatabaseRecordWithEta
88102

89103
return body;
90104
}
105+
106+
static mapRollingDeployment(dateUtil: DateUtil, input: ServerResponse<Record<string, RollingIndexDeployment>>): Record<string, RollingIndexDeployment> {
107+
if (!input) {
108+
return null;
109+
}
110+
111+
const result: Record<string, RollingIndexDeployment> = {};
112+
for (const tag of Object.keys(input)) {
113+
const deployment = input[tag];
114+
result[tag] = {
115+
state: deployment.state,
116+
createdAt: dateUtil.parse(deployment.createdAt),
117+
startedAt: dateUtil.parse(deployment.startedAt),
118+
finishedAt: dateUtil.parse(deployment.finishedAt),
119+
}
120+
}
121+
122+
return result;
123+
}
91124
}

test/Ported/RevisionsTest.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ describe("RevisionsTest", function () {
372372

373373
const revisionsLazilyResult = await revisionsLazy.getValue();
374374

375-
assertThat(revisionsLazilyResult[0] instanceof Company)
375+
assertThat(revisionsLazilyResult[0] instanceof User)
376376
.isTrue();
377377

378378
assertThat(revision.map(x => x.name).join(","))
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { UsersIndex } from "../Assets/Indexes";
2+
import { DocumentConventions, DocumentStore, GetDatabaseRecordOperation } from "../../src";
3+
import { ClusterTestContext, RavenTestContext } from "../Utils/TestUtil";
4+
import { User } from "../Assets/Entities";
5+
import { assertThat } from "../Utils/AssertExtensions";
6+
7+
(RavenTestContext.isPullRequest ? describe.skip : describe)("ClusterModesForRequestExecutorTest", function () {
8+
9+
let testContext: ClusterTestContext;
10+
11+
beforeEach(async function () {
12+
testContext = new ClusterTestContext();
13+
});
14+
15+
afterEach(async () => testContext.dispose());
16+
17+
it("can map rolling indexes types", async function () {
18+
const cluster = await testContext.createRaftCluster(2);
19+
try {
20+
21+
const databaseName = testContext.getDatabaseName();
22+
const numberOfNodes = 2;
23+
24+
await cluster.createDatabase({
25+
databaseName
26+
}, numberOfNodes, cluster.getInitialLeader().url);
27+
28+
29+
let leaderStore: DocumentStore;
30+
try {
31+
leaderStore = new DocumentStore(cluster.getInitialLeader().url, databaseName);
32+
leaderStore.initialize();
33+
34+
{
35+
const session = leaderStore.openSession();
36+
const user = new User();
37+
user.name = "John";
38+
await session.store(user, "users/1-A");
39+
await session.saveChanges();
40+
}
41+
42+
const index = new UsersIndex();
43+
index.deploymentMode = "Rolling";
44+
45+
await leaderStore.executeIndexes([index]);
46+
47+
await testContext.waitForIndexingInTheCluster(leaderStore, leaderStore.database, 10_000);
48+
49+
const databaseRecord = await leaderStore.maintenance.server.send(new GetDatabaseRecordOperation(leaderStore.database));
50+
51+
const indexHistory = databaseRecord.indexesHistory["UsersIndex"][0];
52+
assertThat(indexHistory)
53+
.isNotNull();
54+
55+
assertThat(indexHistory.rollingDeployment)
56+
.isNotNull();
57+
58+
assertThat(indexHistory.rollingDeployment["A"])
59+
.isNotNull();
60+
61+
assertThat(indexHistory.rollingDeployment["A"].startedAt instanceof Date)
62+
.isTrue();
63+
assertThat(indexHistory.rollingDeployment["A"].createdAt instanceof Date)
64+
.isTrue();
65+
assertThat(indexHistory.rollingDeployment["A"].finishedAt instanceof Date)
66+
.isTrue();
67+
} finally {
68+
leaderStore.dispose();
69+
}
70+
} finally {
71+
cluster.dispose();
72+
}
73+
});
74+
});

0 commit comments

Comments
 (0)