Cosmos DB SQL API Node.js - Continuation Token - azure-cosmosdb

I am using the following code to get the list of documents using pagination. The code is working fine. But how do I find the continuation token if I want to send it from the client for pagination.
function queryCollectionPaging() {
return new Promise((resolve, reject) => {
function executeNextWithRetry(iterator, callback) {
iterator.executeNext(function (err, results, responseHeaders) {
if (err) {
return callback(err, null);
}
else {
documents = documents.concat(results);
if (iterator.hasMoreResults()) {
executeNextWithRetry(iterator, callback);
}
else {
callback();
}
}
});
}
let options = {
maxItemCount: 1,
enableCrossPartitionQuery: true
};
let documents = []
let iterator = client.queryDocuments( collectionUrl, 'SELECT r.partitionkey, r.documentid, r._ts FROM root r WHERE r.partitionkey in ("user1", "user2") ORDER BY r._ts', options);
executeNextWithRetry(iterator, function (err, result) {
if (err) {
reject(err)
}
else {
console.log(documents);
resolve(documents)
}
});
});
};

You could find the continuation token in the responseHeaders parameter, please try to use responseHeaders ['x-ms-continuation'] to grab it.
Such as :
continuationToken = responseHeaders ['x-ms-continuation'];
Then you could pass the token as a parameter to the execute method.
let options = {
maxItemCount: 1,
enableCrossPartitionQuery: true,
continuation : continuationToken
};
If the continuationToken is null, it means no more results.
You could refer to my previous case: How to get & set Cosmos Db continuation token in javascript.

Related

Jasmine 4: Async function did not complete within 5000ms issue

I have an existing async function:
async doJSONGetRequest(getUrl, accessToken) {
return new Promise(function(resolve, reject) {
const reqHeaders = {
'Content-Type': 'application/json',
'Authorization': `Bearer ${accessToken}`,
};
console.info('url = ' + getUrl);
request.get({
url: getUrl,
headers: reqHeaders,
}, function(err, response) {
if (err) return reject(err);
try {
// console.debug(`response = ${response.body}`);
const parsed = JSON.parse(response.body);
return resolve(parsed);
} catch (err) {
return reject(err);
}
});
});
}
}
I'm trying to test it with Jasmine(v4).
Of course, I don't want this thing to actually make an HTTP request, so I tried rigging up a spy on the 'request' package's 'get' function in the 'beforeAll' section:
describe('RAPIDAPIService', function() {
beforeAll(async function() {
spyOn(request, 'get')
.and
.callFake(async (parameters) => {
if (parameters.url === 'http://localhost/api/getSomething') {
const rsp = {};
rsp.body = 'good stuff';
return rsp;
} else if (parameters.url === 'http://localhost/api/whoops') {
return new Error('401 not found');
} else {
return null;
}
});
});
it('doJSONGetRequest should run successfully', async () => {
expect(api.doJSONGetRequest).toBeDefined();
const res = await api.doJSONGetRequest('http://localhost/api/getSomething', '12345678');
expect(data).toEqual('good stuff');
});
it('doJSONGetRequest should resolve errors properly', async () => {
expect(api.doJSONGetRequest).toBeDefined();
const res = await api.doJSONGetRequest('http://localhost/api/whoops', '12345678');
const expectedError = new Error('401 not found');
expect(res).toEqual(expectedError);
});
Console log statements seem to indicate that I'm actually getting past / returning something from my "await" calls in the "it" tests. But the spies are actually working / detecting that the url's have been called.
(Note that I'm not including here other tests in the same file that do not make asynchronous calls and ARE working... just so you know that there's no problem accessing the actual "api" library and its functions.)
These two tests keep failing with "Error: Timeout - Async function did not complete within 5000ms". And like I said, it seems like they're not returning back to the tests from their calls to the doJSONGetRequest function.
Any thoughts?
Thanks!
I am thinking the issue is the mocking. request.get seems to take two parameters and I am thinking you need to call the 2nd parameter (callback function) once you are done so the resolve can be called.
Try this:
spyOn(request, 'get')
.and
// add callbackFunction as 2nd argument
.callFake((parameters, callbackFunction) => {
if (parameters.url === 'http://localhost/api/getSomething') {
const rsp = {};
rsp.body = 'good stuff';
callbackFunction(null, rsp);
} else if (parameters.url === 'http://localhost/api/whoops') {
callbackFunction({ error: '401 not found' }, {});
} else {
callbackFunction(null, null);
}
});

how can make synchronous promise in angular2

I am trying to call a function located in service class,and if that function returns data,one boolean variable sets true. I have 2 class as bollow:student.ts and service.ts:
// student.ts
public ngOnInit() {
this.config.load().then(() => {
this.service.getRecords().then(
function () { console.log("success getRecord");
this.loading = false; },
function () { console.log("failed getRecord");
this.loading = true; });
});
}
//service.ts
public getRecord(id: number): Promise<T> {
return this.getRecordImpl();
}
private getRecordsImpl(): Promise<T[]> {
let url = this.serviceUrl;
return this.http.get(url, this.getRequestOptionsWithToken())
.toPromise()
.then(res => {
this.records = this.extractData<T[]>(res);
for (var i = 0; i < this.records.length; i++) {
var record = this.records[i];
this.onRecord(record);
}
return this.records;
})
.catch(this.handleError);
}
by the now, records from service returns, but this.service.getRecords(); is undefined. and I can't use
.then
for handling succeed and failure actions.
I know that it is not good idea to make it synchronous. but think that being Asynchronous causes getRecords becomes undefined. What is the solution for handling that. I want it runs sequentially. and if service returns any records , variable initialize to false, otherwise it sets to true.
Many thanks for any help and guide.
I think your aproach is not correct, what is the point to make a promise synchronous ? If you really really want to do this I suggest you to dig in the Synchronous programming with es6 generators but usually the job is done much smother.
From your code I see that you are consuming your Promise by attaching .then() in the service. In this way you should create a new Promise.
private getRecordsImpl(): Promise<T[]> {
let url = this.serviceUrl;
return new Promise((resolve, reject) => {
this.http.get(url, this.getRequestOptionsWithToken())
.toPromise()
.then(res => {
this.records = this.extractData<T[]>(res);
for (var i = 0; i < this.records.length; i++) {
var record = this.records[i];
this.onRecord(record);
}
resolve(this.records);
})
.catch(this.handleError);
})
}
And in your code use:
this.service.getRecords().then(
function (records) { console.log("success getRecord");
this.loading = false; },
function (err) { console.log("failed getRecord");
this.loading = true; });

Meteor reactive publish

This Meteor code displays a message on a headerLabel on a template, the server and/or the client changes the message by inserting a new message in HeaderLabelCol mongo collection and expect the client template to change since it publishes the last inserted document.
I was able to insert a new message using the client browser but did not show till I refreshed the page which may indicate that the reactiveness chain is broken somewhere. What is the problem? How can it be fixed? Thanks
//client.js
Template.header.helpers({
headerLabel: function () {
return HeaderLabelCol.findOne() ? HeaderLabelCol.findOne().headerLabel : 'Make a selection';
}
});
//server.js
HeaderLabelCol = new Mongo.Collection('headerLabelCol');
Meteor.publish('headerLabelCol', function () {
return HeaderLabelCol.find({userId: this.userId}, { sort: { createdAt: -1 } });
});
HeaderLabelCol._ensureIndex({createdAt: -1});
HeaderLabelCol.before.insert(function (userId, doc) {
doc.userId = userId;
doc.createdAt = Date.now();
});
HeaderLabelCol.allow({
insert: function (userId, doc) {
return (userId && doc.owner === userId);
}
});
I think you need to add the condition in your helper as well.
//client.js
Template.header.helpers({
headerLabel: function () {
var result = HeaderLabelCol.findOne({}, { sort: { createdAt: -1 } });
return result ? result.headerLabel : 'Make a selection';
}
});

adding a field to a user after created

This code attempts to add a field to a user which already exist in meteor users.
The error I am getting is
Exception while invoking method 'logMeIn' Error: insert requires an argument
Which I don't understand, how can it be fixed? Thanks
/////////////////////////////////////
// client code
/////////////////////////////////////
Template.login.events({
'click #logMe': function() {
var username = $('#id').val();
var password = $('#pin').val();
Meteor.call('logMeIn', [username,password], function (err, data) { //create new user
if ( err ) {
if (err.message.match(/username already exists/i)) {
Meteor.loginWithPassword(username+password,password)
}
} else {
console.log('new user created');
}
});
}
});
/////////////////////////////////////
// server code
/////////////////////////////////////
Meteor.methods({
logMeIn: function (credentials) {
//do work , if logged in, do next line
var idPin = credentials[0] + credentials[1];
Accounts.createUser({username: idPin, password: credentials[1]});
}
});
Accounts.onCreateUser(function (options, user) {
user.menuGroup = 'a';
});
You need to return the user on the Account.onCreatedUser (documentation here). Also, additional data of the user should be put under the profile branch (check the documentation in here)
Accounts.onCreateUser(function (options, user) {
if (options.profile) {
user.profile = options.profile;
}
if (user['profile'] == null) {
user['profile'] = {};
}
user['profile']['menuGroup'] = 'a';
return user;
});

How do I write a Firebase timestamp and write it again to another location

I am using Firebase.ServerValue.TIMESTAMP at one location within the firebase.
After I write it, I would like to also store that same value at another location.
Is there a shortcut to do this? For example, a way to return the timestamp value that was written? Do I have to read the location of the timestamp back out using .once()?
Thanks in advance,
Aaron
A once() would work okay:
var fb = new Firebase(URL);
fb.set( Firebase.ServerValue.TIMESTAMP, function(err) {
if( !err ) {
fb.once('value', function(snap) {
console.log('the timestamp', snap.val());
});
}
});
You could also utilize a transaction, which passes a snapshot to the success method:
var fb = new Firebase(URL);
fb.transaction(function() {
return Firebase.ServerValue.TIMESTAMP;
}, function(err, success, snap) {
if( err ) { console.error(err); }
else { console.log('the timestamp', snap.val()); }
});

Resources