Skip to content

Instantly share code, notes, and snippets.

@zachlankton
Last active November 13, 2021 19:07
Show Gist options
  • Save zachlankton/aaaa7d6d1cc1ee34e0974bc1ee05b191 to your computer and use it in GitHub Desktop.
Save zachlankton/aaaa7d6d1cc1ee34e0974bc1ee05b191 to your computer and use it in GitHub Desktop.
A test script to reproduce an intermittent error that occurs when using ottoman.js for couchbase
// This script reproduces an intermittent error that occurs when using ottoman.js start() stand alone function
// it runs 3 separate tests:
// 1. Using Ottoman start() stand alone function
// 2. Using Ottoman with seperate ensureCollections and ensureIndexes with a Pause
// 3. Using Couchbase Node.js SDK (no pause)
// 4. Using Couchbase Node.js SDK with a pause
// run this script in a terminal with:
// node ottoman-test.mjs
/* eslint-disable no-unused-vars */
import { start, Schema, model, Ottoman } from "ottoman";
import {
Cluster,
DurabilityLevel,
BucketType,
CompressionMode,
EvictionPolicy,
ConflictResolutionType,
} from "couchbase";
import { exit, stdout } from "process";
const ottoman = new Ottoman();
const cnx = {
connectionString: "couchbase://localhost",
bucketName: "test",
username: "Administrator",
password: "1234567890",
};
const UserSchema = new Schema(
{
userid: { type: String, required: true },
firstName: String,
lastName: String,
username: String,
street: String,
city: String,
state: String,
zipCode: Number,
name: String,
phone: String,
email: String,
},
{
timestamps: true,
}
);
model("UserProfile", UserSchema, {
idKey: "userid",
});
let cbase = null;
let countIndexError = 0;
let timeouts = 0;
let runFunction;
const seed = async () => {
try {
cbase = await Cluster.connect(cnx.connectionString, {
username: cnx.username,
password: cnx.password,
});
await DropAndCreateTestBucket();
await runFunction();
stdout.write("-")
} catch (e) {
if (e.first_error_code === 12003) {
countIndexError += 1;
stdout.write("e")
} else if (e.message === "timeout") {
timeouts += 1;
stdout.write("t")
} else {
stdout.write(` ${e.message} `)
}
}
};
async function runOttomanWithStart() {
await cbase.close();
await ottoman.connect(cnx);
await ottoman.ensureCollections();
await ottoman.ensureIndexes();
}
async function runOttomanWithPause() {
await ottoman.connect(cnx);
await ottoman.ensureCollections();
await pause(1000);
await ottoman.ensureIndexes();
}
async function runWithCouchbase() {
await cbase
.bucket(cnx.bucketName)
.collections()
.createCollection("UserProfile", "_default");
await cbase.query(
"CREATE INDEX `Ottoman_defaultUserProfile` ON `" +
cnx.bucketName +
'`.`_default`.`UserProfile`(`_type`) USING GSI WITH {"defer_build": true}'
);
await cbase.query(
"BUILD INDEX ON `" +
cnx.bucketName +
"`.`_default`.`UserProfile`(`Ottoman_defaultUserProfile`) USING GSI"
);
}
async function runWithCouchbasePause() {
await cbase
.bucket(cnx.bucketName)
.collections()
.createCollection("UserProfile", "_default");
await pause(1000);
await cbase.query(
"CREATE INDEX `Ottoman_defaultUserProfile` ON `" +
cnx.bucketName +
'`.`_default`.`UserProfile`(`_type`) USING GSI WITH {"defer_build": true}'
);
await cbase.query(
"BUILD INDEX ON `" +
cnx.bucketName +
"`.`_default`.`UserProfile`(`Ottoman_defaultUserProfile`) USING GSI"
);
}
async function DropAndCreateTestBucket() {
await cbase
.buckets()
.dropBucket("test")
.catch(() => 0);
await pause(2500);
await cbase
.buckets()
.createBucket({
conflictResolutionType: ConflictResolutionType.SequenceNumber,
ejectionMethod: EvictionPolicy.ValueOnly,
name: "test",
flushEnabled: false,
ramQuotaMB: 2048,
numReplicas: 1,
replicaIndexes: false,
bucketType: BucketType.Couchbase,
evictionPolicy: EvictionPolicy.ValueOnly,
maxExpiry: 0,
compressionMode: CompressionMode.Passive,
minimumDurabilityLevel: DurabilityLevel.None,
maxTTL: 0,
durabilityMinLevel: "none",
})
.catch((e) => {
console.error(e);
exit();
});
await pause(2500);
}
function pause(n) {
// eslint-disable-next-line no-undef
return new Promise((resolve) => {
setTimeout(() => {
resolve(true);
}, n);
});
}
const numTests = 10;
async function runTest() {
for (let i = 0; i < numTests; i++) {
stdout.write(` ${i + 1}`)
await seed();
}
const passed = numTests - countIndexError - timeouts;
console.log(`\n\tPASSED\tFAILED\tTIMEOUT\tTOTAL`)
console.log(`\t ${passed}\t ${countIndexError}\t ${timeouts}\t ${numTests}`)
countIndexError = 0;
timeouts = 0;
}
async function runTests() {
stdout.write("\nTesting Ottoman with Start....");
runFunction = runOttomanWithStart;
await runTest();
stdout.write("\nTesting Ottoman with Pause....");
runFunction = runOttomanWithPause;
await runTest();
stdout.write("\nTesting with Couchbase....");
runFunction = runWithCouchbase;
await runTest();
stdout.write("\nTesting with Couchbase Pause...");
runFunction = runWithCouchbasePause;
await runTest();
exit();
}
runTests();
// run this script in a terminal with:
// node ottoman-test.mjs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment